From 6e765fe1edcb835f26e45d5e177dfd3ad108573e Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Tue, 23 Dec 2025 09:09:20 -0800 Subject: [PATCH] clarify comment in PSOV2Encryption::single --- src/PSOEncryption.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/PSOEncryption.cc b/src/PSOEncryption.cc index 14d76530..3bc4720e 100644 --- a/src/PSOEncryption.cc +++ b/src/PSOEncryption.cc @@ -111,7 +111,9 @@ uint32_t PSOV2Encryption::single(uint32_t seed) { // If fib(n) is the n'th Fibonacci number (starting with 1, 1, 2, 3, 5, etc.), then a closed form for the integer // sequence generated by the first loop in PSOV2Encryption::PSOV2Encryption is: // a(n) = (-1)^n * (fib(n) - fib(n-1) * seed) - // The recurrence used in that loop is a(n) = a(n-2) - a(n-1), which we can use to prove the closed form correct: + // The sequence begins with a(-1) = seed (which is not generated by the loop but is used as an initial input, hence + // the negative index) and a(0) = 1, and the recurrence used in that loop is a(n) = a(n-2) - a(n-1). Assuming that + // a(n-2) and a(n-1) are described by this closed form, we can show that a(n) is as well: // a(n) = a(n-2) - a(n-1) // a(n) = (-1)^(n-2) * (fib(n-2) - fib(n-3) * seed) - ((-1)^(n-1) * (fib(n-1) - fib(n-2) * seed)) // a(n) = (-1)^(n-2) * (fib(n-2) - fib(n-3) * seed) + ((-1)^(n-2) * (fib(n-1) - fib(n-2) * seed)) @@ -119,13 +121,13 @@ uint32_t PSOV2Encryption::single(uint32_t seed) { // a(n) = (-1)^(n-2) * (fib(n-2) + fib(n-1) - (fib(n-3) + fib(n-2)) * seed) // a(n) = (-1)^(n-2) * (fib(n) - fib(n-1) * seed) // a(n) = (-1)^(n) * (fib(n) - fib(n-1) * seed) - // The sequence begins with a(-1) = seed (which is not generated by the loop but is used as an initial input, hence - // the negative index) and a(0) = 1. Using the closed form and the values of a(-1) and a(0), we can eliminate all - // arithmetic done in the normal constructor that isn't necessary to produce the first result value. To do so, we - // trace backward from the result value, through the 5 update_stream calls and the initialization loop, to see which - // indexes within the stream are actually needed, and the expression to generate each one. We can then simplify the - // overall expression and truncate constants to 32 bits (since it's a linear equation, overflow bits cannot affect - // the final 32-bit result). The full expression simplifies to: + // This shows inductively that this closed form holds for all n >= 1 (since the sequence begins with a(-1)). Using + // the closed form and the values of a(-1) and a(0), we can eliminate all arithmetic done in the normal constructor + // that isn't necessary to produce the first result value. To do so, we trace backward from the result value, through + // the 5 update_stream calls and the initialization loop, to see which indexes within the stream are actually needed, + // and the expression to generate each one. We can then simplify the overall expression and truncate constants to 32 + // bits (since it's a linear equation, overflow bits cannot affect the final 32-bit result). The full expression + // simplifies to: return 0xC6DCAB76 * seed - 0x9E1977BA; }