Repository: osmosis-labs/osmosis (go)

Issue:
docs(osmomath): estimate error bounds for `BigDec` `Power`
In https://github.com/osmosis-labs/osmosis/pull/3731, we added a `Power` function that takes a decimal exponent.

Currently, the error is unbounded.

As per https://github.com/osmosis-labs/osmosis/pull/3731#discussion_r1052773354, we should investigate what the bounds are exactly

**Acceptance Criteria**
- absolute and relative error bounds are defined and documented.

Pull request description:
refactor: delete unused Power function in osmomath
Deletes the unused Power function in osmomath/decimal.go and its test in decimal_test.go, as this function is not currently in use and is never called within the codebase. PowerInteger remains intact for integer exponents.

Closes #3800

Patch:
diff --git a/osmomath/decimal.go b/osmomath/decimal.go
index ca2f15bad..ed5bc6c99 100644
--- a/osmomath/decimal.go
+++ b/osmomath/decimal.go
@@ -1180,46 +1180,3 @@ func (d BigDec) PowerIntegerMut(power uint64) BigDec {
 
 	return d.MulMut(tmp)
 }
-
-// Power returns a result of raising the given big dec to
-// a positive decimal power. Panics if the power is negative.
-// Panics if the base is negative. Does not mutate the receiver.
-// The max supported exponent is defined by the global maxSupportedExponent.
-// If a greater exponent is given, the function panics.
-// The error is not bounded but expected to be around 10^-18, use with care.
-// See the underlying Exp2, LogBase2 and Mul for the details of their bounds.
-// WARNING: This function is broken for base < 1. The reason is that logarithm function is
-// negative between zero and 1, and the Exp2(k) is undefined for negative k.
-// As a result, this function panics if called for d < 1.
-func (d BigDec) Power(power BigDec) BigDec {
-	if d.IsNegative() {
-		panic(fmt.Sprintf("negative base is not supported for Power(), base was (%s)", d))
-	}
-	if power.IsNegative() {
-		panic(fmt.Sprintf("negative power is not supported for Power(), power was (%s)", power))
-	}
-	if power.Abs().GT(maxSupportedExponent) {
-		panic(fmt.Sprintf("integer exponent %s is too large, max (%s)", power, maxSupportedExponent))
-	}
-	// TODO: Potentially expensive??
-	if power.IsInteger() {
-		return d.PowerInteger(power.TruncateInt().Uint64())
-	}
-	if power.IsZero() {
-		return OneBigDec()
-	}
-	if d.IsZero() {
-		return ZeroBigDec()
-	}
-	if d.LT(oneBigDec) {
-		panic(fmt.Sprintf("Power() is not supported for base < 1, base was (%s)", d))
-	}
-	if d.Equal(twoBigDec) {
-		return Exp2(power)
-	}
-
-	// d^power = exp2(power * log_2{base})
-	result := Exp2(d.LogBase2().Mul(power))
-
-	return result
-}


Test patch:
diff --git a/osmomath/decimal_test.go b/osmomath/decimal_test.go
index 98e8d2a16..70609e6b5 100644
--- a/osmomath/decimal_test.go
+++ b/osmomath/decimal_test.go
@@ -1268,7 +1268,7 @@ func (s *decimalTestSuite) TestPowerInteger() {
 			// positive integer, we also test Power().
 			// Negative exponent and base are not supported for Power()
 			if tc.exponent >= 0 && !tc.base.IsNegative() {
-				actualResult2 := tc.base.Power(osmomath.NewBigDecFromInt(osmomath.NewBigIntFromUint64(tc.exponent)))
+				actualResult2 := tc.base.PowerInteger(tc.exponent)
 				require.True(osmomath.DecApproxEq(s.T(), tc.expectedResult, actualResult2, tolerance))
 			}
 		})
@@ -1384,121 +1384,6 @@ func (s *decimalTestSuite) TestPowerInteger_Mutation() {
 	}
 }
 
-func (s *decimalTestSuite) TestPower() {
-	tests := map[string]struct {
-		base           osmomath.BigDec
-		exponent       osmomath.BigDec
-		expectedResult osmomath.BigDec
-		expectPanic    bool
-		errTolerance   osmomath.ErrTolerance
-	}{
-		// N.B.: integer exponents are tested under TestPowerInteger.
-
-		"3 ^ 2 = 9 (integer base and integer exponent)": {
-			base:     osmomath.NewBigDec(3),
-			exponent: osmomath.NewBigDec(2),
-
-			expectedResult: osmomath.NewBigDec(9),
-
-			errTolerance: zeroAdditiveErrTolerance,
-		},
-		"2^0.5 (base of 2 and non-integer exponent)": {
-			base:     osmomath.MustNewBigDecFromStr("2"),
-			exponent: osmomath.MustNewBigDecFromStr("0.5"),
-
-			// https://www.wolframalpha.com/input?i=2%5E0.5+37+digits
-			expectedResult: osmomath.MustNewBigDecFromStr("1.414213562373095048801688724209698079"),
-
-			errTolerance: osmomath.ErrTolerance{
-				AdditiveTolerance: minDecTolerance,
-				RoundingDir:       osmomath.RoundDown,
-			},
-		},
-		"3^0.33 (integer base other than 2 and non-integer exponent)": {
-			base:     osmomath.MustNewBigDecFromStr("3"),
-			exponent: osmomath.MustNewBigDecFromStr("0.33"),
-
-			// https://www.wolframalpha.com/input?i=3%5E0.33+37+digits
-			expectedResult: osmomath.MustNewBigDecFromStr("1.436977652184851654252692986409357265"),
-
-			errTolerance: osmomath.ErrTolerance{
-				AdditiveTolerance: minDecTolerance,
-				RoundingDir:       osmomath.RoundDown,
-			},
-		},
-		"e^0.98999 (non-integer base and non-integer exponent)": {
-			base:     osmomath.EulersNumber,
-			exponent: osmomath.MustNewBigDecFromStr("0.9899"),
-
-			// https://www.wolframalpha.com/input?i=e%5E0.9899+37+digits
-			expectedResult: osmomath.MustNewBigDecFromStr("2.690965362357751196751808686902156603"),
-
-			errTolerance: osmomath.ErrTolerance{
-				AdditiveTolerance: minDecTolerance,
-				RoundingDir:       osmomath.RoundUnconstrained,
-			},
-		},
-		"10^0.001 (small non-integer exponent)": {
-			base:     osmomath.NewBigDec(10),
-			exponent: osmomath.MustNewBigDecFromStr("0.001"),
-
-			// https://www.wolframalpha.com/input?i=10%5E0.001+37+digits
-			expectedResult: osmomath.MustNewBigDecFromStr("1.002305238077899671915404889328110554"),
-
-			errTolerance: osmomath.ErrTolerance{
-				AdditiveTolerance: minDecTolerance,
-				RoundingDir:       osmomath.RoundUnconstrained,
-			},
-		},
-		"13^100.7777 (large non-integer exponent)": {
-			base:     osmomath.NewBigDec(13),
-			exponent: osmomath.MustNewBigDecFromStr("100.7777"),
-
-			// https://www.wolframalpha.com/input?i=13%5E100.7777+37+digits
-			expectedResult: osmomath.MustNewBigDecFromStr("1.822422110233759706998600329118969132").Mul(osmomath.NewBigDec(10).PowerInteger(112)),
-
-			errTolerance: osmomath.ErrTolerance{
-				MultiplicativeTolerance: minDecTolerance,
-				RoundingDir:             osmomath.RoundDown,
-			},
-		},
-		"large non-integer exponent with large non-integer base - panics": {
-			base:     osmomath.MustNewBigDecFromStr("169.137"),
-			exponent: osmomath.MustNewBigDecFromStr("100.7777"),
-
-			expectPanic: true,
-		},
-		"negative base - panic": {
-			base:     osmomath.NewBigDec(-3),
-			exponent: osmomath.MustNewBigDecFromStr("4"),
-
-			expectPanic: true,
-		},
-		"negative exponent - panic": {
-			base:     osmomath.NewBigDec(1),
-			exponent: osmomath.MustNewBigDecFromStr("-4"),
-
-			expectPanic: true,
-		},
-		"base < 1 - panic (see godoc)": {
-			base:     osmomath.NewBigDec(1).Sub(osmomath.SmallestBigDec()),
-			exponent: osmomath.OneBigDec(),
-
-			expectPanic: true,
-		},
-	}
-
-	for name, tc := range tests {
-		tc := tc
-		s.Run(name, func() {
-			osmomath.ConditionalPanic(s.T(), tc.expectPanic, func() {
-				actualResult := tc.base.Power(tc.exponent)
-				osmomath.Equal(s.T(), tc.errTolerance, tc.expectedResult, actualResult)
-			})
-		})
-	}
-}
-
 func (s *decimalTestSuite) TestDec_WithPrecision() {
 	tests := []struct {
 		d         osmomath.BigDec