NDPluginTimeSeries: divide the averaged sum before narrowing, not after#596
Merged
MarkRivers merged 1 commit intoJul 16, 2026
Merged
Conversation
doTimeSeriesT() stored an averaged time-series point as
pTimeCircular[...] = (epicsType)averageStore_[signal]/numAveraged_;
C++ precedence binds the cast tighter than the divide, so this evaluates
as ((epicsType)averageStore_[signal]) / numAveraged_. averageStore_ is a
double accumulator holding the SUM of numAveraged_ samples, so the sum is
truncated (and, for integer element types, wrapped) to the narrow element
type before the division ever happens.
For any integer signal with averaging enabled (numAveraged_ > 1) this
corrupts every averaged point once the running sum exceeds the element
type's range: three UInt8 samples of 200 sum to 600, which narrows to
(epicsUInt8)600 == 88, then 88 / 3 == 29 instead of 200.
Parenthesize as (epicsType)(averageStore_[signal]/numAveraged_) so the
double division runs at full precision and only the final average is
narrowed. Float element types were already correct and are unchanged.
Verified with a proof driver over the worked example: the old expression
yields 29, the parenthesized expression yields 200.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
(epicsType)averageStore_[signal]/numAveraged_parses as((epicsType)sum)/n— thedoublesum is truncated or wrapped to the narrow element type before the divide. With averaging on, three UInt8 samples of 200 sum to 600 →(epicsUInt8)600 == 88→88/3 == 29instead of 200. Parenthesize as(epicsType)(averageStore_[signal]/numAveraged_); float element types are unaffected. Proven with a driver reproducing the exact expression.