package math import ( "math/big" "sync" "github.com/holiman/uint256" "github.com/fraktal/mev-beta/pkg/uniswap" ) // Cached mathematical constants to avoid recomputation var ( cachedConstantsOnce sync.Once cachedQ192 *big.Int cachedQ96 *big.Int cachedQ384 *big.Int cachedTwoPower96 *big.Float cachedTwoPower192 *big.Float cachedTwoPower384 *big.Float ) // initCachedConstants initializes all cached constants once func initCachedConstants() { cachedConstantsOnce.Do(func() { // Calculate 2^96 cachedQ96 = new(big.Int).Exp(big.NewInt(2), big.NewInt(96), nil) // Calculate 2^192 cachedQ192 = new(big.Int).Exp(big.NewInt(2), big.NewInt(192), nil) // Calculate 2^384 cachedQ384 = new(big.Int).Exp(big.NewInt(2), big.NewInt(384), nil) // Convert to big.Float for division operations cachedTwoPower96 = new(big.Float).SetInt(cachedQ96) cachedTwoPower192 = new(big.Float).SetInt(cachedQ192) cachedTwoPower384 = new(big.Float).SetInt(cachedQ384) }) } // GetCachedQ192 returns the cached value of 2^192 func GetCachedQ192() *big.Int { initCachedConstants() return cachedQ192 } // GetCachedQ96 returns the cached value of 2^96 func GetCachedQ96() *big.Int { initCachedConstants() return cachedQ96 } // GetCachedQ384 returns the cached value of 2^384 func GetCachedQ384() *big.Int { initCachedConstants() return cachedQ384 } // SqrtPriceX96ToPriceCached converts sqrtPriceX96 to a price using cached constants // Formula: price = sqrtPriceX96^2 / 2^192 func SqrtPriceX96ToPriceCached(sqrtPriceX96 *big.Int) *big.Float { initCachedConstants() // Convert to big.Float for precision sqrtPriceFloat := new(big.Float).SetInt(sqrtPriceX96) // Calculate sqrtPrice^2 price := new(big.Float).Mul(sqrtPriceFloat, sqrtPriceFloat) // Divide by 2^192 using cached constant price.Quo(price, cachedTwoPower192) return price } // PriceToSqrtPriceX96Cached converts a price to sqrtPriceX96 using cached constants // Formula: sqrtPriceX96 = sqrt(price * 2^192) func PriceToSqrtPriceX96Cached(price *big.Float) *big.Int { initCachedConstants() // Multiply price by 2^192 result := new(big.Float).Mul(price, cachedTwoPower192) // Calculate square root result.Sqrt(result) // Convert to big.Int sqrtPriceX96 := new(big.Int) result.Int(sqrtPriceX96) return sqrtPriceX96 } // SqrtPriceX96ToPriceOptimized converts sqrtPriceX96 to a price using optimized uint256 operations // Formula: price = sqrtPriceX96^2 / 2^192 func SqrtPriceX96ToPriceOptimized(sqrtPriceX96 *uint256.Int) *big.Float { initCachedConstants() // Convert to big.Int for calculation sqrtPriceBig := sqrtPriceX96.ToBig() // Use cached function for consistency return SqrtPriceX96ToPriceCached(sqrtPriceBig) } // PriceToSqrtPriceX96Optimized converts a price to sqrtPriceX96 using optimized operations // Formula: sqrtPriceX96 = sqrt(price * 2^192) func PriceToSqrtPriceX96Optimized(price *big.Float) *uint256.Int { initCachedConstants() // Use cached function for consistency sqrtPriceBig := PriceToSqrtPriceX96Cached(price) // Convert to uint256 return uint256.MustFromBig(sqrtPriceBig) } // TickToSqrtPriceX96Optimized calculates sqrtPriceX96 from a tick using optimized operations // Formula: sqrtPriceX96 = 1.0001^(tick/2) func TickToSqrtPriceX96Optimized(tick int) *uint256.Int { // For simplicity, we'll convert to big.Int and use existing implementation tickBig := big.NewInt(int64(tick)) sqrtPriceBig := uniswap.TickToSqrtPriceX96(int(tickBig.Int64())) return uint256.MustFromBig(sqrtPriceBig) }