Potential rounding issues (and updating comments) #742
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What has been Changed
The comments look like they belong a few lines higher up.
What might need to be changed - Units: Seconds vs Nanoseconds
Here
math.Log2(float64(period))
will convertperiod
into afloat64
which is the nanoseconds for that duration. When we do the calculations we operate overuint64(period.Seconds())
. So there are two different units being compares.The implications are that
periodBits
will be about 30 bits (log2(10^9)
) higher, as it is in nanoseconds rather than if it were based off seconds.As an example, using period = 10 seconds gives a total of
periodBits = log2(1,500,000,000) = 33.8
.math.MaxUint64 >> int(periodBits) ~= 2^(64 - 33)
Then the if statement will throw an error if
round > 2^(64 - 33)
.At 10 seconds periods that's about 608 years (2^31 * 10 seconds) worth of rounds.
This actually protects against the next two issues so it may be worth leaving but at least adding a comment to explain why.
Potential Issue 1: Rounding overflow
If
periodBits
actually represented the amount of bits of period in seconds e.g.periodBits := math.Log2(float64(int(period.Seconds()) + 1))
assuming period >= 0Then
int(periodBits)
is potentially trauncating a bit.Example, say
period = 10
uses 4 bits.periodBits := math.Log2(float64(int(period.Seconds()) + 1)) = log2(10 + 1) = 3.4
int(periodBits) = 3
.So set
round = math.MaxUint64 >> 3
thus the if statement does not errorround > (math.MaxUint64 >> int(periodBits))
We then have
10 * ((math.MathUint64 >> 3) - 1)
which overflows.Potential Issue 2
Carrying on from above, the cast
int64(delta)
, wheredelta
isuint64
may overflow. Overflow occurs if the most significant bit set to 1 i.e.delta >= 2^63
in which caseint64(delta)
would cast a large positive number to a negative number and be successfully returned.Solution
Working on the assumption here that
period >= 0
which should be fine for drand since theperiod
wouldn't not be set to negative. But maybe, for extra safety, add a check to ensureperiod >= 0
.Or alternatively as mentioned above leave it as is and add a comment to explain why we use the nanoseconds not seconds.