From 5c185b386c1d80b5ab5c081a8c89e4f901ee409b Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Sun, 23 May 2021 01:31:54 +1000 Subject: [PATCH] Adjust RNG algorithm --- docs/rng.md | 4 +++- pyRCV2/random/sharandom_js.py | 4 ++-- pyRCV2/random/sharandom_py.py | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/rng.md b/docs/rng.md index 37ec5a8..86386b1 100644 --- a/docs/rng.md +++ b/docs/rng.md @@ -6,6 +6,8 @@ The algorithm takes a *seed* value, which is an arbitrary character string. The In order to generate a value between 0 (inclusive) and *n* (exclusive), to the state is appended a comma (",") followed by the value of the counter, and a SHA-256 hash *H* is computed of the resulting string encoded using UTF-8. The hash *H* is represented as an unsigned hexadecimal integer, *k*. The counter is incremented by 1. -In order to avoid modulo bias, if *k* ≥ ⌊*M*/*n*⌋ × *n* (where *M* is the maximum possible value of *k*, 2^256 - 1), *k* is discarded and the algorithm is repeated. +In order to avoid modulo bias, if *k* ≥ ⌊*M*/*n*⌋ × *n* (where *M* = 2^256), *k* is discarded and the algorithm is repeated. Otherwise, the result is *k* modulo *n*. + +In revision [86695aa](https://yingtongli.me/git/pyRCV2/commit/?id=86695aa67e2af936a84d78cb7a7aed9844f61ca9) and older, a slightly different formula was in use to avoid modulo bias – see the documentation of previous revisions for details. It is theoretically possible, though overwhelmingly unlikely, that this may result in different outcomes. diff --git a/pyRCV2/random/sharandom_js.py b/pyRCV2/random/sharandom_js.py index 49e9509..77edf8c 100644 --- a/pyRCV2/random/sharandom_js.py +++ b/pyRCV2/random/sharandom_js.py @@ -1,5 +1,5 @@ # pyRCV2: Preferential vote counting -# Copyright © 2020 Lee Yingtong Li (RunasSudo) +# Copyright © 2020–2021 Lee Yingtong Li (RunasSudo) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -15,7 +15,7 @@ # along with this program. If not, see . if __pragma__('js', '{}', 'typeof(bigInt)') != 'undefined': - _MAX_VAL = bigInt(2).pow(256).subtract(1) + _MAX_VAL = bigInt(2).pow(256) else: # Fail gracefully if dependencies not present _MAX_VAL = None diff --git a/pyRCV2/random/sharandom_py.py b/pyRCV2/random/sharandom_py.py index 7322ab4..6525694 100644 --- a/pyRCV2/random/sharandom_py.py +++ b/pyRCV2/random/sharandom_py.py @@ -1,5 +1,5 @@ # pyRCV2: Preferential vote counting -# Copyright © 2020 Lee Yingtong Li (RunasSudo) +# Copyright © 2020–2021 Lee Yingtong Li (RunasSudo) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -17,7 +17,7 @@ import hashlib class SHARandom: - MAX_VAL = 2 ** 256 - 1 + MAX_VAL = 2 ** 256 def __init__(self, seed): self.seed = seed