mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-03 18:22:25 -06:00 
			
		
		
		
	* Add SQLite support, fix un-thread-safe DB caches, small performance fixes Signed-off-by: kim (grufwub) <grufwub@gmail.com> * add SQLite licenses to README Signed-off-by: kim (grufwub) <grufwub@gmail.com> * appease the linter, and fix my dumbass-ery Signed-off-by: kim (grufwub) <grufwub@gmail.com> * make requested changes Signed-off-by: kim (grufwub) <grufwub@gmail.com> * add back comment Signed-off-by: kim (grufwub) <grufwub@gmail.com>
		
			
				
	
	
		
			279 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			279 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright (c) 2018 The mathutil Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package mathutil // import "modernc.org/mathutil"
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"math"
 | 
						|
	"math/big"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	// MaxInt128 represents the maximun Int128 value as big.Int
 | 
						|
	MaxInt128 *big.Int
 | 
						|
	// MinInt128 represents the minimun Int128 value as big.Int
 | 
						|
	MinInt128 *big.Int
 | 
						|
	// MaxUint128 represents the maximun Uint128 value as big.Int
 | 
						|
	MaxUint128 *big.Int
 | 
						|
)
 | 
						|
 | 
						|
func init() {
 | 
						|
	var ok bool
 | 
						|
	MaxInt128, ok = big.NewInt(0).SetString("0x7fffffff_ffffffff_ffffffff_ffffffff", 0)
 | 
						|
	if !ok {
 | 
						|
		panic("internal error")
 | 
						|
	}
 | 
						|
 | 
						|
	MinInt128 = big.NewInt(0).Set(MaxInt128)
 | 
						|
	MinInt128.Add(MinInt128, _1)
 | 
						|
	MinInt128.Neg(MinInt128)
 | 
						|
 | 
						|
	MaxUint128, ok = big.NewInt(0).SetString("0xffffffff_ffffffff_ffffffff_ffffffff", 0)
 | 
						|
	if !ok {
 | 
						|
		panic("internal error")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
const (
 | 
						|
	maxInt128  = 1<<127 - 1
 | 
						|
	maxUint128 = 1<<128 - 1
 | 
						|
	minInt128  = -maxInt128 - 1
 | 
						|
)
 | 
						|
 | 
						|
// Int128 is an 128 bit signed integer.
 | 
						|
type Int128 struct {
 | 
						|
	Lo int64 // Bits 63..0.
 | 
						|
	Hi int64 // Bits 127..64.
 | 
						|
}
 | 
						|
 | 
						|
// Add returns the sum of x and y and a carry indication.
 | 
						|
func (x Int128) Add(y Int128) (r Int128, cy bool) {
 | 
						|
	r.Lo = x.Lo + y.Lo
 | 
						|
	r.Hi = x.Hi + y.Hi
 | 
						|
	if uint64(r.Lo) < uint64(x.Lo) {
 | 
						|
		r.Hi++
 | 
						|
	}
 | 
						|
	return r, (r.Cmp(x) < 0) == (y.Sign() >= 0)
 | 
						|
}
 | 
						|
 | 
						|
// BigInt returns x in the form of a big.Int.
 | 
						|
func (x Int128) BigInt() *big.Int {
 | 
						|
	r := big.NewInt(x.Hi)
 | 
						|
	r.Lsh(r, 64)
 | 
						|
	lo := big.NewInt(0)
 | 
						|
	lo.SetUint64(uint64(x.Lo))
 | 
						|
	return r.Add(r, lo)
 | 
						|
}
 | 
						|
 | 
						|
// Cmp compares x and y and returns:
 | 
						|
//
 | 
						|
//	-1 if x <  y
 | 
						|
//	 0 if x == y
 | 
						|
//	+1 if x >  y
 | 
						|
func (x Int128) Cmp(y Int128) int {
 | 
						|
	if x.Hi > y.Hi {
 | 
						|
		return 1
 | 
						|
	}
 | 
						|
 | 
						|
	if x.Hi < y.Hi {
 | 
						|
		return -1
 | 
						|
	}
 | 
						|
 | 
						|
	if uint64(x.Lo) > uint64(y.Lo) {
 | 
						|
		return 1
 | 
						|
	}
 | 
						|
 | 
						|
	if uint64(x.Lo) < uint64(y.Lo) {
 | 
						|
		return -1
 | 
						|
	}
 | 
						|
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
// Neg returns -x and an indication that x was not equal to MinInt128.
 | 
						|
func (x Int128) Neg() (r Int128, ok bool) {
 | 
						|
	if x == (Int128{Hi: math.MinInt64}) {
 | 
						|
		return x, false
 | 
						|
	}
 | 
						|
 | 
						|
	x.Lo = ^x.Lo
 | 
						|
	x.Hi = ^x.Hi
 | 
						|
	r, _ = x.Add(Int128{Lo: 1})
 | 
						|
	return r, true
 | 
						|
}
 | 
						|
 | 
						|
// SetBigInt sets x to y, returns x and an error, if any.
 | 
						|
func (x *Int128) SetBigInt(y *big.Int) (r Int128, err error) {
 | 
						|
	if y.Cmp(MaxInt128) > 0 {
 | 
						|
		return *x, fmt.Errorf("%T.SetInt: overflow", x)
 | 
						|
	}
 | 
						|
	if y.Cmp(MinInt128) < 0 {
 | 
						|
		return *x, fmt.Errorf("%T.SetInt: underflow", x)
 | 
						|
	}
 | 
						|
	neg := y.Sign() < 0
 | 
						|
	var z big.Int
 | 
						|
	z.Set(y)
 | 
						|
	if neg {
 | 
						|
		z.Neg(&z)
 | 
						|
	}
 | 
						|
	r.Lo = z.Int64()
 | 
						|
	z.Rsh(&z, 64)
 | 
						|
	r.Hi = z.Int64()
 | 
						|
	if neg {
 | 
						|
		r, _ = r.Neg()
 | 
						|
	}
 | 
						|
	*x = r
 | 
						|
	return r, nil
 | 
						|
}
 | 
						|
 | 
						|
// SetInt64 sets x to y and returns x.
 | 
						|
func (x *Int128) SetInt64(y int64) (r Int128) {
 | 
						|
	r.Lo = y
 | 
						|
	if y >= 0 {
 | 
						|
		r.Hi = 0
 | 
						|
		*x = r
 | 
						|
		return r
 | 
						|
	}
 | 
						|
 | 
						|
	r.Hi = -1
 | 
						|
	*x = r
 | 
						|
	return r
 | 
						|
}
 | 
						|
 | 
						|
// SetUint64 sets x to y and returns x.
 | 
						|
func (x *Int128) SetUint64(y uint64) (r Int128) {
 | 
						|
	r = Int128{Lo: int64(y)}
 | 
						|
	*x = r
 | 
						|
	return r
 | 
						|
}
 | 
						|
 | 
						|
// Sign returns:
 | 
						|
//
 | 
						|
//	-1 if x <  0
 | 
						|
//	 0 if x == 0
 | 
						|
//	+1 if x >  0
 | 
						|
func (x Int128) Sign() int {
 | 
						|
	if x.Hi < 0 {
 | 
						|
		return -1
 | 
						|
	}
 | 
						|
 | 
						|
	if x.Hi != 0 || x.Lo != 0 {
 | 
						|
		return 1
 | 
						|
	}
 | 
						|
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
// String implements fmt.Stringer()
 | 
						|
func (x Int128) String() string { return x.BigInt().String() }
 | 
						|
 | 
						|
// NewInt128FromInt64 return a new Int128 value initialized to n.
 | 
						|
func NewInt128FromInt64(n int64) (r Int128) {
 | 
						|
	r.Lo = n
 | 
						|
	if n < 0 {
 | 
						|
		r.Hi = -1
 | 
						|
	}
 | 
						|
	return r
 | 
						|
}
 | 
						|
 | 
						|
// NewInt128FromUint64 return a new Int128 value initialized to n.
 | 
						|
func NewInt128FromUint64(n uint64) (r Int128) { return Int128{Lo: int64(n)} }
 | 
						|
 | 
						|
// NewInt128FromFloat32 returns a new Int128 value initialized to n. Result is
 | 
						|
// not specified in n does not represent a number within the range of Int128
 | 
						|
// values.
 | 
						|
func NewInt128FromFloat32(n float32) (r Int128) {
 | 
						|
	if n >= minInt128 && n <= maxInt128 {
 | 
						|
		if n >= math.MinInt64 && n <= math.MaxInt64 {
 | 
						|
			return NewInt128FromInt64(int64(n))
 | 
						|
		}
 | 
						|
 | 
						|
		f := big.NewFloat(float64(n))
 | 
						|
		bi, _ := f.Int(nil)
 | 
						|
		r.SetBigInt(bi)
 | 
						|
	}
 | 
						|
	return r
 | 
						|
}
 | 
						|
 | 
						|
// NewInt128FromFloat64 returns a new Int128 value initialized to n. Result is
 | 
						|
// not specified in n does not represent a number within the range of Int128
 | 
						|
// values.
 | 
						|
func NewInt128FromFloat64(n float64) (r Int128) {
 | 
						|
	if n >= minInt128 && n <= maxInt128 {
 | 
						|
		if n >= math.MinInt64 && n <= math.MaxInt64 {
 | 
						|
			return NewInt128FromInt64(int64(n))
 | 
						|
		}
 | 
						|
 | 
						|
		f := big.NewFloat(n)
 | 
						|
		bi, _ := f.Int(nil)
 | 
						|
		r.SetBigInt(bi)
 | 
						|
	}
 | 
						|
	return r
 | 
						|
}
 | 
						|
 | 
						|
// Uint128 is an 128 bit unsigned integer.
 | 
						|
type Uint128 struct {
 | 
						|
	Lo uint64 // Bits 63..0.
 | 
						|
	Hi uint64 // Bits 127..64.
 | 
						|
}
 | 
						|
 | 
						|
// NewUint128FromInt64 return a new Uint128 value initialized to n.
 | 
						|
func NewUint128FromInt64(n int64) (r Uint128) {
 | 
						|
	r.Lo = uint64(n)
 | 
						|
	if n < 0 {
 | 
						|
		r.Hi = ^uint64(0)
 | 
						|
	}
 | 
						|
	return r
 | 
						|
}
 | 
						|
 | 
						|
// NewUint128FromUint64 return a new Uint128 value initialized to n.
 | 
						|
func NewUint128FromUint64(n uint64) (r Uint128) { return Uint128{Lo: n} }
 | 
						|
 | 
						|
// NewUint128FromFloat32 returns a new Uint128 value initialized to n. Result is
 | 
						|
// not specified in n does not represent a number within the range of Uint128
 | 
						|
// values.
 | 
						|
func NewUint128FromFloat32(n float32) (r Uint128) {
 | 
						|
	if n >= 0 {
 | 
						|
		if n <= math.MaxUint64 {
 | 
						|
			return NewUint128FromUint64(uint64(n))
 | 
						|
		}
 | 
						|
 | 
						|
		f := big.NewFloat(float64(n))
 | 
						|
		bi, _ := f.Int(nil)
 | 
						|
		r.SetBigInt(bi)
 | 
						|
	}
 | 
						|
	return r
 | 
						|
}
 | 
						|
 | 
						|
// NewUint128FromFloat64 returns a new Uint128 value initialized to n. Result is
 | 
						|
// not specified in n does not represent a number within the range of Uint128
 | 
						|
// values.
 | 
						|
func NewUint128FromFloat64(n float64) (r Uint128) {
 | 
						|
	if n >= 0 && n <= maxUint128 {
 | 
						|
		if n <= math.MaxUint64 {
 | 
						|
			return NewUint128FromUint64(uint64(n))
 | 
						|
		}
 | 
						|
 | 
						|
		f := big.NewFloat(n)
 | 
						|
		bi, _ := f.Int(nil)
 | 
						|
		r.SetBigInt(bi)
 | 
						|
	}
 | 
						|
	return r
 | 
						|
}
 | 
						|
 | 
						|
// SetBigInt sets x to y, returns x and an error, if any.
 | 
						|
func (x *Uint128) SetBigInt(y *big.Int) (r Uint128, err error) {
 | 
						|
	if y.Sign() < 0 || y.Cmp(MaxUint128) > 0 {
 | 
						|
		return *x, fmt.Errorf("%T.SetInt: overflow", x)
 | 
						|
	}
 | 
						|
 | 
						|
	var z big.Int
 | 
						|
	z.Set(y)
 | 
						|
	r.Lo = z.Uint64()
 | 
						|
	z.Rsh(&z, 64)
 | 
						|
	r.Hi = z.Uint64()
 | 
						|
	*x = r
 | 
						|
	return r, nil
 | 
						|
}
 |