Skip to content

Fix rescale() silent divide-by-zero on constant/single-element input - #78

Merged
vertesy merged 3 commits into
devfrom
fix/rescale-divide-by-zero
Sep 1, 2026
Merged

vertesy merged 3 commits into
devfrom
fix/rescale-divide-by-zero

Conversation

@vertesy

@vertesy vertesy commented Sep 1, 2026

Copy link
Copy Markdown
Owner

The bug

rescale(vec, from, upto) computed vec - min(vec), then divided by max(vec) of that shifted vector. For a constant vector (or any single-element vector), the shifted vector is all zeros, so max(vec) is 0, and dividing by it silently produces Inf/NaN for every element instead of an error or a meaningful value — no warning is raised.

Fix

Detect the zero-range case (max == min) up front and return the midpoint of the target range, (from + upto) / 2, for all non-NA elements instead. This matches the well-established convention used by scales::rescale() for the identical degenerate-input case (verified: scales::rescale(c(5,5,5), to = c(0,100)) returns c(50,50,50)) — using an existing, widely-used package's behavior as the precedent avoids guessing a novel convention for this edge case.

Verification


Generated by Claude Code

rescale(vec, from, upto) computed vec - min(vec), then divided by
max(vec) of that shifted vector. For a constant vector (or any
single-element vector), the shifted vector is all zeros, so max(vec)
is 0, and dividing by it silently produces Inf/NaN for every element
instead of an error or a meaningful value - no warning is raised.

Fix: detect the zero-range case (max == min) up front and return the
midpoint of the target range, (from + upto) / 2, for all non-NA
elements instead. This matches the well-established convention used
by scales::rescale() for the identical degenerate-input case
(verified: scales::rescale(c(5,5,5), to = c(0,100)) returns
c(50,50,50)) - using an existing, widely-used package's behavior as
the precedent avoids guessing a novel convention for this edge case.

Verified: normal (non-degenerate) input is unaffected; constant
vectors and single-element vectors now return the range midpoint
instead of all-NaN; NA elements are left as NA rather than being
assigned the midpoint; a custom target range on constant input
scales correctly too.

Version bumped 2.8.16 -> 2.8.20 (distinct from sibling PRs #75/#76/#77,
which also branch from the same 2.8.16 base and already claimed
2.8.17/2.8.18/2.8.19).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 26ea755cad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread R/CodeAndRoll2.R Outdated
The constant-input branch computed (from + upto) / 2, which can
overflow to Inf before the division when from and upto are both
large finite numbers (e.g. from = 1e308, upto = 1.1e308 - their sum
exceeds .Machine$double.xmax, so the "midpoint" was Inf instead of
the correct finite 1.05e308).

Fix: compute the midpoint as from + (upto - from) / 2 instead -
the subtraction of two same-magnitude numbers doesn't overflow, and
adding a bounded increment to from doesn't either.

Verified: the flagged overflow case now returns the correct finite
midpoint (1.05e+308) instead of Inf; normal constant-input and
non-degenerate cases are unchanged.
@vertesy

vertesy commented Sep 1, 2026

Copy link
Copy Markdown
Owner Author

@copilot

Could you please verify this pull request by Claude? Claude Code has been introducing many mistakes in recent pull requests, so I require a very critical review from you.

Task 2 is that you resolve the branch conflicts so that I can merge the pull request.

…zero

# Conflicts:
#	DESCRIPTION
#	Development/config.R

Co-authored-by: vertesy <5101911+vertesy@users.noreply.github.com>

Copilot AI commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

@copilot

Could you please verify this pull request by Claude? Claude Code has been introducing many mistakes in recent pull requests, so I require a very critical review from you.
...

I reviewed Claude's fix critically: rescale() now checks vmax == vmin up front and returns from + (upto - from) / 2 for the degenerate case (constant/single-element vectors), which avoids the original divide-by-zero, correctly preserves NA elements, and avoids overflow (verified from + upto could overflow for huge finite values, so the code uses the subtraction-based midpoint instead). The normal, non-degenerate path is unchanged. I found no issues with the logic.

Branch conflicts are resolved: merged dev into this branch, keeping version 2.8.20 (ahead of dev's 2.8.19) in DESCRIPTION/Development/config.R. The PR should be mergeable now.

@vertesy
vertesy merged commit 9b343ff into dev Sep 1, 2026
@vertesy
vertesy deleted the fix/rescale-divide-by-zero branch September 1, 2026 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants