Skip to content

Commit

Permalink
fix prime=0 selected for domain=1
Browse files Browse the repository at this point in the history
  • Loading branch information
jfolz committed Oct 13, 2024
1 parent 01dad06 commit 9bfb1d9
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Fixed
- Very large seeds no longer cause integer overflow
- 0 is no longer selected as coprime for domain=1


## [0.0.2] - 2024-10-12
Expand Down
11 changes: 10 additions & 1 deletion shufflish/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ def _modular_prime_combinations(domain, primes, k):
Generate all ``k``-combinations of the given primes that are unique mod ``domain``.
Only considers primes that are coprime with ``domain``.
"""
if domain == 1:
yield 1
return
primes = list(dict.fromkeys(p % domain for p in primes if domain % p != 0))
seen = set()
ones = (1,) * (k-1)
Expand All @@ -96,6 +99,9 @@ def _modular_prime_combinations_with_repetition(domain, primes, k):
Only considers primes that are coprime with ``domain``.
May repeat values.
"""
if domain == 1:
yield 1
return
ones = (1,) * (k-1)
primes = list(dict.fromkeys(p % domain for p in primes if domain % p != 0))
for p1, p2, p3 in combinations(chain(ones, primes), k):
Expand Down Expand Up @@ -196,6 +202,8 @@ def _select_prime(
Only considers primes that are coprime with ``domain``.
This can be quite slow.
"""
if domain == 1:
return 1
gen = _modular_prime_combinations(domain, primes, k)
num_comb = None
if primes is PRIMES and domain in NUM_COMBINATIONS:
Expand All @@ -221,6 +229,8 @@ def _select_prime_with_repetition(
Return the product of this combination mod domain.
This is reasonably fast, but does not account for reptitions mod domain.
"""
if domain == 1:
return 1
ones = (1,) * (k-1)
primes = list(chain(ones, dict.fromkeys(p % domain for p in primes if domain % p != 0)))
np = len(primes)
Expand Down Expand Up @@ -302,7 +312,6 @@ def permutation(
raise ValueError("domain must be < 2**63")
if seed is None:
seed = random.randrange(2**64)
# Step 1: Select coprime number
if allow_repetition:
prime = _select_prime_with_repetition(domain, seed, primes, num_primes)
else:
Expand Down
7 changes: 4 additions & 3 deletions test/test_completeness.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ def _is_complete(p, domain):
assert len(set(p)) == domain, (p, domain)


def test_permutations_class():
def test_permutations_function():
for domain in (1, 2, 3, 5, 7, 10, 11, 13, 100):
for seed in range(domain):
_is_complete(permutation(domain, seed), domain)


def test_permutation_function():
def test_permutation_class():
for domain in (1, 2, 3, 5, 7, 10, 11, 13, 100):
perms = Permutations(domain)
print(perms.coprimes)
assert len(perms.coprimes) > 0, domain
for seed in range(domain):
for seed in range(domain * len(perms.coprimes)):
_is_complete(perms.get(seed), domain)


Expand Down

0 comments on commit 9bfb1d9

Please sign in to comment.