Skip to content

Commit ac00bc6

Browse files
committed
findTopCellItem() handle underflow (f20-3)
1 parent 837b61b commit ac00bc6

File tree

1 file changed

+18
-21
lines changed

1 file changed

+18
-21
lines changed

Meter.c

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,6 @@ static uint8_t GraphMeterMode_findTopCellItem(const Meter* this, double scaledTo
386386
assert(topCell < graphHeight);
387387

388388
double valueSum = 0.0;
389-
bool maxValueIsArea = false;
390389
double maxValue = 0.0;
391390
uint8_t topCellItem = this->curItems - 1;
392391
for (uint8_t i = 0; i < this->curItems && valueSum < DBL_MAX; i++) {
@@ -410,35 +409,33 @@ static uint8_t GraphMeterMode_findTopCellItem(const Meter* this, double scaledTo
410409
// Find the item that occupies the largest area of the top cell.
411410
// Favor item with higher index in case of a tie.
412411

413-
double area = (value / scaledTotal) * (double)(int)graphHeight;
414-
assert(area >= 0.0);
415-
416-
if (topCellItem > i) {
417-
assert(!maxValueIsArea);
418-
assert(maxValue <= 0.0);
419-
412+
if (topCell > 0) {
420413
double topPoint = (valueSum / scaledTotal) * (double)(int)graphHeight;
421414
assert(topPoint >= 0.0);
422415

423-
if (topCell > 0 && !(topPoint > (double)(int)topCell))
416+
if (!(topPoint > (double)(int)topCell))
424417
continue;
425418

426-
if (area > topPoint - (double)(int)topCell) {
427-
maxValueIsArea = true;
428-
maxValue = topPoint - (double)(int)topCell;
429-
} else {
430-
maxValue = value;
431-
}
432-
topCellItem = i;
433-
} else if (maxValueIsArea) {
419+
double area = (value / scaledTotal) * (double)(int)graphHeight;
420+
assert(area >= 0.0);
421+
422+
if (area > topPoint - (double)(int)topCell)
423+
area = topPoint - (double)(int)topCell;
424+
425+
// Note: The FP default rounding mode (i.e. to nearest) ensures any
426+
// "area" that could win to have a number at least (DBL_EPSILON / 2).
427+
434428
if (area >= maxValue) {
435-
maxValueIsArea = false;
429+
maxValue = area;
430+
topCellItem = i;
431+
}
432+
} else {
433+
// Compare "value" directly. It is possible for an "area" to
434+
// underflow here, and still wins as the largest area.
435+
if (value >= maxValue) {
436436
maxValue = value;
437437
topCellItem = i;
438438
}
439-
} else if (value >= maxValue) {
440-
maxValue = value;
441-
topCellItem = i;
442439
}
443440
}
444441
return topCellItem;

0 commit comments

Comments
 (0)