Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fixed-point WithinTolerance method and greater-than operators #1135

Merged
merged 2 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions rfq/negotiator.go
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,8 @@ func expiryWithinBounds(expiryUnixTimestamp uint64,

// priceWithinBounds returns true if the difference between the first price and
// the second price is within the given tolerance (in parts per million (PPM)).
//
// TODO(ffranr): Replace with FixedPoint[T].WithinTolerance.
ffranr marked this conversation as resolved.
Show resolved Hide resolved
func pricesWithinBounds(firstPrice lnwire.MilliSatoshi,
secondPrice lnwire.MilliSatoshi, tolerancePpm uint64) bool {

Expand Down
29 changes: 29 additions & 0 deletions rfqmath/arithmetic.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ type Int[N any] interface {
// Equals returns true if the two integers are equal.
Equals(other N) bool

// Gt returns true if the integer is greater than the other integer.
Gt(other N) bool

// Gte returns true if the integer is greater than or equal to the other
// integer.
Gte(other N) bool

// ToFloat converts the integer to a float.
ToFloat() float64

Expand Down Expand Up @@ -121,6 +128,17 @@ func (b GoInt[T]) Equals(other GoInt[T]) bool {
return b.value == other.value
}

// Gt returns true if the integer is greater than the other integer.
func (b GoInt[T]) Gt(other GoInt[T]) bool {
return b.value > other.value
}

// Gte returns true if the integer is greater than or equal to the other
// integer.
func (b GoInt[T]) Gte(other GoInt[T]) bool {
return b.value >= other.value
}

// A compile-time constraint to ensure that the GoInt type implements the Int
// interface.
var _ Int[GoInt[uint]] = GoInt[uint]{}
Expand Down Expand Up @@ -208,6 +226,17 @@ func (b BigInt) Equals(other BigInt) bool {
return b.value.Cmp(other.value) == 0
}

// Gt returns true if the integer is greater than the other integer.
func (b BigInt) Gt(other BigInt) bool {
return b.value.Cmp(other.value) == 1
}

// Gte returns true if the integer is greater than or equal to the other
// integer.
func (b BigInt) Gte(other BigInt) bool {
return b.Equals(other) || b.Gt(other)
}

// A compile-time constraint to ensure that the BigInt type implements the Int
// interface.
var _ Int[BigInt] = BigInt{}
47 changes: 47 additions & 0 deletions rfqmath/fixed_point.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,53 @@ func (f FixedPoint[T]) Equals(other FixedPoint[T]) bool {
return f.Coefficient.Equals(other.Coefficient) && f.Scale == other.Scale
}

// WithinTolerance returns true if the two FixedPoint values are within the
// given tolerance (in parts per million (PPM)).
func (f FixedPoint[T]) WithinTolerance(
Roasbeef marked this conversation as resolved.
Show resolved Hide resolved
other FixedPoint[T], tolerancePpm T) bool {

// Determine the larger scale between the two fixed-point numbers.
// Both values will be scaled to this larger scale to ensure a
// consistent comparison.
var largerScale uint8
if f.Scale > other.Scale {
largerScale = f.Scale
} else {
largerScale = other.Scale
}
ffranr marked this conversation as resolved.
Show resolved Hide resolved

subjectFp := f.ScaleTo(largerScale)
otherFp := other.ScaleTo(largerScale)

var (
// delta will be the absolute difference between the two
// coefficients.
delta T

// maxCoefficient is the larger of the two coefficients.
maxCoefficient T
)
if subjectFp.Coefficient.Gt(otherFp.Coefficient) {
delta = subjectFp.Coefficient.Sub(otherFp.Coefficient)
maxCoefficient = subjectFp.Coefficient
} else {
delta = otherFp.Coefficient.Sub(subjectFp.Coefficient)
maxCoefficient = otherFp.Coefficient
}

// Calculate the tolerance in absolute terms based on the largest
// coefficient.
//
// tolerancePpm is parts per million, therefore we multiply the delta by
// 1,000,000 instead of dividing the tolerance.
scaledDelta := delta.Mul(NewInt[T]().FromUint64(1_000_000))

// Compare the scaled delta to the product of the maximum coefficient
// and the tolerance.
toleranceCoefficient := maxCoefficient.Mul(tolerancePpm)
return toleranceCoefficient.Gte(scaledDelta)
}

// FixedPointFromUint64 creates a new FixedPoint from the given integer and
// scale. Note that the input here should be *unscaled*.
func FixedPointFromUint64[N Int[N]](value uint64, scale uint8) FixedPoint[N] {
Expand Down
Loading
Loading