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

Fix countdown through 0 for uint32 #19926

Open
wants to merge 4 commits into
base: devel
Choose a base branch
from

Conversation

etan-status
Copy link
Contributor

  • countdown on an uint32 down to 0 underflows the counter, because
    the default int based implementation is applied.
  • countdown on an uint64 down to 0 with non-1 step underflows the
    counter, because the cancel condition does not consider such steps.
  • countdown on distinct uint64 down to 0 underflows the counter,
    because the default implementation is applied.

Corrected by replacing the default implementation with the safe uint
one, and by correcting the cancellation condition for non-1 step.

- `countdown` on an `uint32` down to 0 underflows the counter, because
  the default `int` based implementation is applied.
- `countdown` on an `uint64` down to 0 with non-1 `step` underflows the
  counter, because the cancel condition does not consider such steps.
- `countdown` on distinct `uint64` down to 0 underflows the counter,
  because the default implementation is applied.

Corrected by replacing the default implementation with the safe `uint`
one, and by correcting the cancellation condition for non-1 `step`.
@@ -38,6 +37,7 @@ iterator countdown*[T](a, b: T, step: Positive = 1): T {.inline.} =
var res = a
while res >= b:
yield res
if res <= succ(b, step.Natural - 1): break
Copy link
Member

Choose a reason for hiding this comment

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

Not acceptable. Bloat plus a false sense of "correctness". If you bump into the boundaries of the numeric types that you use, use different numeric types such as a BigInt.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Any unsigned type stops at 0, regardless of how wide it is. Things like countdown(5.uint64, 0.uint64, 2) won't work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

re bloat, could you elaborate? The generated code seems to emit a constant for the entire succ(b, step.Natural - 1).

Copy link
Contributor

Choose a reason for hiding this comment

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

If you bump into the boundaries of the numeric types that you use, use different numeric types such as a BigInt.

unsigned integers wrap by definition - they're used in contexts where that wrapping is desirable and a different numeric type such as BigInt would simply be wrong - it has a different semantic - the whole point of using unsigned types is that you're looking for a certain behavior at the boundary, and often exploit it - the inability to use for with some uint sizes is a significant gotcha for the language.

@github-actions
Copy link
Contributor

This pull request is stale because it has been open for 1 year with no activity. Contribute more commits on the pull request and rebase it on the latest devel, or it will be closed in 30 days. Thank you for your contributions.

@github-actions github-actions bot added the stale Staled PR/issues; remove the label after fixing them label Jun 28, 2023
@etan-status
Copy link
Contributor Author

Bumped to latest devel

@etan-status
Copy link
Contributor Author

Windows failure seems unrelated:

2023-06-28T11:35:09.4253985Z Category: misc
2023-06-28T11:35:09.4254634Z Name: tests/misc/trunner_special.nim cpp
2023-06-28T11:35:09.4255036Z Action: run
2023-06-28T11:35:09.4255444Z Result: reExitcodesDiffer
2023-06-28T11:35:09.4255757Z -------- Expected -------
2023-06-28T11:35:09.4256018Z exitcode: 0
2023-06-28T11:35:09.4256314Z --------- Given  --------
2023-06-28T11:35:09.4256609Z exitcode: 1
2023-06-28T11:35:09.4256772Z 
2023-06-28T11:35:09.4257050Z Output:
2023-06-28T11:35:09.4257207Z 
2023-06-28T11:35:09.4257468Z [Suite] SSL certificate check - disabled
2023-06-28T11:35:09.4257814Z thttpclient_ssl_disabled.nim(35) thttpclient_ssl_disabled
2023-06-28T11:35:09.4258147Z net.nim(2068)            connect
2023-06-28T11:35:09.4258420Z oserrors.nim(92)         raiseOSError
2023-06-28T11:35:09.4258634Z 
2023-06-28T11:35:09.4259044Z     Unhandled exception: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
2023-06-28T11:35:09.4259469Z  [OSError]
2023-06-28T11:35:09.4259773Z   [FAILED] net socket in insecure mode
2023-06-28T11:35:09.4260311Z system.nim(369)          thttpclient_ssl_disabled
2023-06-28T11:35:09.4260641Z fatal.nim(53)            sysFatal
2023-06-28T11:35:09.4260986Z Error: unhandled exception: no exception to reraise [ReraiseDefect]
2023-06-28T11:35:09.4261460Z Error: execution of an external program failed: 'C:\Users\VssAdministrator\nimcache\thttpclient_ssl_disabled_d\thttpclient_ssl_disabled_489B5FE00AF7C3C3A25E26763FD249291D65690B.exe'
2023-06-28T11:35:09.4261882Z D:\a\1\s\tests\misc\trunner_special.nim(22, 12): Check failed: ret == 0
2023-06-28T11:35:09.4262261Z ret was 1
2023-06-28T11:35:09.4262417Z 
2023-06-28T11:35:09.4262708Z -------------------------
2023-06-28T11:35:09.4262883Z 
2023-06-28T11:35:09.4263163Z Category: misc
2023-06-28T11:35:09.4263435Z Name: tests/misc/trunner_special.nim cpp
2023-06-28T11:35:09.4263744Z Action: run
2023-06-28T11:35:09.4264043Z Result: reExitcodesDiffer
2023-06-28T11:35:09.4264334Z -------- Expected -------
2023-06-28T11:35:09.4264554Z 
2023-06-28T11:35:09.4264794Z --------- Given  --------
2023-06-28T11:35:09.4265272Z $ D:\a\1\s\bin\nim.exe cpp --hints:on -d:testing --nimblePath:build/deps/pkgs2   --nimCache:nimcache\tests\misc\trunner_special.nim_2c5f2cba9af7f92986d3de1e753f3faa  tests\misc\trunner_special.nim

@github-actions github-actions bot removed the stale Staled PR/issues; remove the label after fixing them label Jun 29, 2023
@haoyu234
Copy link
Contributor

I have two other solutions, there is no need to compare more than once in the loop

solution 1

  when T is (uint|uint64):
    if a >= b:
      yield a

      var res = a
      var n = int((a - b) div T(step))

      while n > 0:
        dec(res, step)
        dec(n, 1)

        yield res

solution 2

  when T is (uint|uint64):
    if a >= b:
      yield a

      var res = a
      var nb = b + T((a - b) mod T(step))

      while res > nb:
        dec(res, step)

        yield T(res)

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.

None yet

4 participants