Skip to content

Commit b078457

Browse files
committed
rfqmath: add FixedPoint[T].WithinTolerance method
This commit introduces the WithinTolerance method to FixedPoint[T]. The method checks if two fixed-point numbers are within a given tolerance, specified in Parts Per Million (PPM), and returns true if they are.
1 parent 867a72c commit b078457

File tree

3 files changed

+421
-0
lines changed

3 files changed

+421
-0
lines changed

rfq/negotiator.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,8 @@ func expiryWithinBounds(expiryUnixTimestamp uint64,
518518

519519
// priceWithinBounds returns true if the difference between the first price and
520520
// the second price is within the given tolerance (in parts per million (PPM)).
521+
//
522+
// TODO(ffranr): Replace with FixedPoint[T].WithinTolerance.
521523
func pricesWithinBounds(firstPrice lnwire.MilliSatoshi,
522524
secondPrice lnwire.MilliSatoshi, tolerancePpm uint64) bool {
523525

rfqmath/fixed_point.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,53 @@ func (f FixedPoint[T]) Equals(other FixedPoint[T]) bool {
103103
return f.Coefficient.Equals(other.Coefficient) && f.Scale == other.Scale
104104
}
105105

106+
// WithinTolerance returns true if the two FixedPoint values are within the
107+
// given tolerance (in parts per million (PPM)).
108+
func (f FixedPoint[T]) WithinTolerance(
109+
other FixedPoint[T], tolerancePpm T) bool {
110+
111+
// Determine the larger scale between the two fixed-point numbers.
112+
// Both values will be scaled to this larger scale to ensure a
113+
// consistent comparison.
114+
var largerScale uint8
115+
if f.Scale > other.Scale {
116+
largerScale = f.Scale
117+
} else {
118+
largerScale = other.Scale
119+
}
120+
121+
subjectFp := f.ScaleTo(largerScale)
122+
otherFp := other.ScaleTo(largerScale)
123+
124+
var (
125+
// delta will be the absolute difference between the two
126+
// coefficients.
127+
delta T
128+
129+
// maxCoefficient is the larger of the two coefficients.
130+
maxCoefficient T
131+
)
132+
if subjectFp.Coefficient.Gt(otherFp.Coefficient) {
133+
delta = subjectFp.Coefficient.Sub(otherFp.Coefficient)
134+
maxCoefficient = subjectFp.Coefficient
135+
} else {
136+
delta = otherFp.Coefficient.Sub(subjectFp.Coefficient)
137+
maxCoefficient = otherFp.Coefficient
138+
}
139+
140+
// Calculate the tolerance in absolute terms based on the largest
141+
// coefficient.
142+
//
143+
// tolerancePpm is parts per million, therefore we multiply the delta by
144+
// 1,000,000 instead of dividing the tolerance.
145+
scaledDelta := delta.Mul(NewInt[T]().FromUint64(1_000_000))
146+
147+
// Compare the scaled delta to the product of the maximum coefficient
148+
// and the tolerance.
149+
toleranceCoefficient := maxCoefficient.Mul(tolerancePpm)
150+
return toleranceCoefficient.Gte(scaledDelta)
151+
}
152+
106153
// FixedPointFromUint64 creates a new FixedPoint from the given integer and
107154
// scale. Note that the input here should be *unscaled*.
108155
func FixedPointFromUint64[N Int[N]](value uint64, scale uint8) FixedPoint[N] {

0 commit comments

Comments
 (0)