package lookup import ( "math/big" "sync" ) var ( // Lookup tables for frequently used values sqrt10001Table map[int]*big.Float q96Table *big.Int q192Table *big.Int // Once variables for initializing lookup tables sqrt10001Once sync.Once q96Once sync.Once ) // initSqrt10001Table initializes the lookup table for sqrt(1.0001^n) func initSqrt10001Table() { sqrt10001Once.Do(func() { sqrt10001Table = make(map[int]*big.Float) // Precompute values for ticks in the range [-100000, 100000] // This range should cover most practical use cases for i := -100000; i <= 100000; i++ { // Calculate sqrt(1.0001^i) base := 1.0001 power := float64(i) / 2.0 result := pow(base, power) // Store in lookup table sqrt10001Table[i] = new(big.Float).SetFloat64(result) } }) } // initQTables initializes the lookup tables for Q96 and Q192 func initQTables() { q96Once.Do(func() { // Q96 = 2^96 q96Table = new(big.Int).Exp(big.NewInt(2), big.NewInt(96), nil) // Q192 = 2^192 = (2^96)^2 q192Table = new(big.Int).Exp(big.NewInt(2), big.NewInt(192), nil) }) } // GetSqrt10001 retrieves the precomputed sqrt(1.0001^n) value func GetSqrt10001(n int) *big.Float { initSqrt10001Table() // Check if value is in lookup table if val, ok := sqrt10001Table[n]; ok { return val } // If not in lookup table, compute it base := 1.0001 power := float64(n) / 2.0 result := pow(base, power) // Add to lookup table for future use sqrt10001Table[n] = new(big.Float).SetFloat64(result) return sqrt10001Table[n] } // GetQ96 retrieves the precomputed Q96 value (2^96) func GetQ96() *big.Int { initQTables() return q96Table } // GetQ192 retrieves the precomputed Q192 value (2^192) func GetQ192() *big.Int { initQTables() return q192Table } // Helper function for computing powers efficiently func pow(base, exp float64) float64 { if exp == 0 { return 1 } if exp == 1 { return base } if exp == 2 { return base * base } // For other values, use exponentiation by squaring return powInt(base, int(exp)) } // Integer power function using exponentiation by squaring func powInt(base float64, exp int) float64 { if exp < 0 { return 1.0 / powInt(base, -exp) } result := 1.0 for exp > 0 { if exp&1 == 1 { result *= base } base *= base exp >>= 1 } return result }