; reversible random number generator
(define (euclid x y)
(let loop ((a 1) (b 0) (g x) (u 0) (v 1) (w y))
(if (zero? w) (values a b g)
(let ((q (quotient g w)))
(loop u v w (- a (* q u)) (- b (* q v)) (- g (* q w)))))))
(define (inverse x m)
(if (not (= (gcd x m) 1))
(error 'inverse "divisor must be coprime to modulus")
(call-with-values
(lambda () (euclid x m))
(lambda (a b g) (modulo a m)))))
(define next #f)
(define prev #f)
(let ((a 69069) (c 1234567) (m (expt 2 32)))
(set! next (lambda (x) (modulo (+ (* a x) c) m)))
(set! prev (lambda (x) (modulo (* (inverse a m) (- x c)) m))))
(display (next 2718281828)) (newline)
(display (next 3103402651)) (newline)
(display (next 4281062310)) (newline)
(display (prev 1670430837)) (newline)
(display (prev 4281062310)) (newline)
(display (prev 3103402651)) (newline)
OyByZXZlcnNpYmxlIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yCgooZGVmaW5lIChldWNsaWQgeCB5KQogIChsZXQgbG9vcCAoKGEgMSkgKGIgMCkgKGcgeCkgKHUgMCkgKHYgMSkgKHcgeSkpCiAgICAoaWYgKHplcm8/IHcpICh2YWx1ZXMgYSBiIGcpCiAgICAgIChsZXQgKChxIChxdW90aWVudCBnIHcpKSkKICAgICAgICAobG9vcCB1IHYgdyAoLSBhICgqIHEgdSkpICgtIGIgKCogcSB2KSkgKC0gZyAoKiBxIHcpKSkpKSkpCgooZGVmaW5lIChpbnZlcnNlIHggbSkKICAoaWYgKG5vdCAoPSAoZ2NkIHggbSkgMSkpCiAgICAgIChlcnJvciAnaW52ZXJzZSAiZGl2aXNvciBtdXN0IGJlIGNvcHJpbWUgdG8gbW9kdWx1cyIpCiAgICAgIChjYWxsLXdpdGgtdmFsdWVzCiAgICAgICAgKGxhbWJkYSAoKSAoZXVjbGlkIHggbSkpCiAgICAgICAgKGxhbWJkYSAoYSBiIGcpIChtb2R1bG8gYSBtKSkpKSkKCihkZWZpbmUgbmV4dCAjZikKKGRlZmluZSBwcmV2ICNmKQoKKGxldCAoKGEgNjkwNjkpIChjIDEyMzQ1NjcpIChtIChleHB0IDIgMzIpKSkKICAoc2V0ISBuZXh0IChsYW1iZGEgKHgpIChtb2R1bG8gKCsgKCogYSB4KSBjKSBtKSkpCiAgKHNldCEgcHJldiAobGFtYmRhICh4KSAobW9kdWxvICgqIChpbnZlcnNlIGEgbSkgKC0geCBjKSkgbSkpKSkKCihkaXNwbGF5IChuZXh0IDI3MTgyODE4MjgpKSAobmV3bGluZSkKKGRpc3BsYXkgKG5leHQgMzEwMzQwMjY1MSkpIChuZXdsaW5lKQooZGlzcGxheSAobmV4dCA0MjgxMDYyMzEwKSkgKG5ld2xpbmUpCihkaXNwbGF5IChwcmV2IDE2NzA0MzA4MzcpKSAobmV3bGluZSkKKGRpc3BsYXkgKHByZXYgNDI4MTA2MjMxMCkpIChuZXdsaW5lKQooZGlzcGxheSAocHJldiAzMTAzNDAyNjUxKSkgKG5ld2xpbmUp