Subtractive generator: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
(Rename Perl 6 -> Raku, alphabetize, minor clean-up)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(25 intermediate revisions by 17 users not shown)
Line 36:
Implement a subtractive generator that replicates the sequences from ''xpat2''.
<br><br>
 
=={{header|11l}}==
{{trans|Python: With explanation}}
 
<syntaxhighlight lang="11l">Deque[Int] s
V seed = 292929
 
s.append(seed)
s.append(1)
 
L(n) 2..54
s.append((s[n - 2] - s[n - 1]) % 10 ^ 9)
 
Deque[Int] r
L(n) 55
V i = (34 * (n + 1)) % 55
r.append(s[i])
 
F py_mod(a, b)
R ((a % b) + b) % b
 
F getnextr()
:r.append(py_mod((:r[0] - :r[31]), 10 ^ 9))
:r.pop_left()
R :r[54]
 
L 0 .< 219 - 54
getnextr()
 
L 5
print(‘result = ’getnextr())</syntaxhighlight>
 
{{out}}
<pre>
result = 467478574
result = 512932792
result = 539453717
result = 20349702
result = 615542081
</pre>
 
=={{header|Ada}}==
 
subtractive_generator.ads:
<langsyntaxhighlight Adalang="ada">package Subtractive_Generator is
type State is private;
procedure Initialize (Generator : in out State; Seed : Natural);
Line 50 ⟶ 90:
Last : Natural;
end record;
end Subtractive_Generator;</langsyntaxhighlight>
 
subtractive_generator.adb:
<langsyntaxhighlight Adalang="ada">package body Subtractive_Generator is
 
procedure Initialize (Generator : in out State; Seed : Natural) is
Line 85 ⟶ 125:
end Next;
 
end Subtractive_Generator;</langsyntaxhighlight>
 
Example main.adb:
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO;
with Subtractive_Generator;
 
Line 101 ⟶ 141:
Ada.Text_IO.Put_Line (Integer'Image (I) & ":" & Integer'Image (N));
end loop;
end Main;</langsyntaxhighlight>
 
{{out}}
Line 110 ⟶ 150:
=={{header|AutoHotkey}}==
{{works with|AutoHotkey_L}}
<langsyntaxhighlight AutoHotkeylang="autohotkey">r := InitR(292929)
 
Loop, 10
Line 134 ⟶ 174:
, r[i] := Mod(r[i] - r[Mod(A_Index + 30, 55)], r["m"])
return, r
}</langsyntaxhighlight>
{{out}}
<pre>220: 467478574
Line 147 ⟶ 187:
229: 380969305</pre>
 
=={{header|BBC BASIC}}==
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> dummy% = FNsubrand(292929)
FOR i% = 1 TO 10
PRINT FNsubrand(0)
Line 174 ⟶ 215:
IF FNsubrand(0)
NEXT
= 0</langsyntaxhighlight>
{{out}}
<pre>
Line 187 ⟶ 228:
506003769
380969305
</pre>
 
==={{header|FreeBASIC}}===
{{trans|Kotlin}}
<syntaxhighlight lang="vb">Const As Integer mod_ = 1e9
Dim Shared As Integer state(0 To 55)
Dim Shared As Integer sk = 0, sj = 0
 
Declare Function subrand() As Integer
 
Sub subrandSeed (p1 As Integer)
Dim As Integer i, j, p2
state(0) = p1 Mod mod_
p2 = 1
j = 21
For i = 1 To 54
If j >= 55 Then j -= 55
state(j) = p2
p2 = p1 - p2
If p2 < 0 Then p2 += mod_
p1 = state(j)
j += 21
Next
sk = 0
sj = 24
For i = 1 To 165
subrand()
Next
End Sub
 
Function subrand() As Integer
If sk = sj Then
subrandSeed(0)
Else
If sk = 0 Then sk = 54 Else sk -= 1
If sj = 0 Then sj = 54 Else sj -= 1
Dim As Integer x = state(sk) - state(sj)
If x < 0 Then x += mod_
state(sk) = x
Return x
End If
End Function
 
subrandSeed(292929)
For i As Integer = 0 To 9
Print Using "r[###] = &"; i+220; subrand()
Next i
 
Sleep</syntaxhighlight>
{{out}}
<pre>Same as Kotlin entry</pre>
 
==={{header|Gambas}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vbnet">Public mod_ As Integer = 1e9
Public state[55] As Integer
Public sk As Integer = 0
Public sj As Integer = 0
 
Public Sub Main()
subrandSeed(292929)
For i As Integer = 0 To 9
Print "r["; i + 220; "] = "; subrand()
Next
End
 
Sub subrandSeed(p1 As Integer)
 
Dim i As Integer
Dim p2 As Integer = 1
Dim j As Integer = 21
 
state[0] = p1 Mod mod_
For i = 1 To 54
If j >= 55 Then j -= 55
state[j] = p2
p2 = p1 - p2
If p2 < 0 Then p2 += mod_
p1 = state[j]
j += 21
Next
sk = 0
sj = 24
For i = 1 To 165
subrand()
Next
 
End Sub
 
Function subrand() As Integer
If sk = sj Then
subrandSeed(0)
Else
If sk = 0 Then sk = 54 Else sk -= 1
If sj = 0 Then sj = 54 Else sj -= 1
Dim x As Integer = state[sk] - state[sj]
If x < 0 Then x += mod_
state[sk] = x
Return x
End If
 
End Function</syntaxhighlight>
 
==={{header|uBasic/4tH}}===
<syntaxhighlight lang="text">Push 292929 : Gosub 100 : d = Pop()
 
For i = 1 To 10
Push 0 : Gosub 100
Print Pop()
Next
 
End
 
100 s = Pop()
If s = 0 Then
p = (p + 1) % 55
@(p) = @(p) - @((p + 31) % 55)
If @(p) < 0 Then
@(p) = @(p) + 1000000000
Endif
Push (@(p)) : Return
Endif
 
@(54) = s : @(33) = 1
p = 12
 
For i = 2 To 54
@(p) = @((p + 42) % 55) - @((p + 21) % 55)
If @(p) < 0 Then
@(p) = @(p) + 1000000000
Endif
p = (p + 34) % 55
Next
 
For i = 55 To 219
Push 0 : Gosub 100 : d = Pop()
Next
 
Push 0 : Return</syntaxhighlight>
{{out}}
<pre>467478574
512932792
539453717
20349702
615542081
378707948
933204586
824858649
506003769
380969305
 
0 OK, 0:864
</pre>
 
Line 192 ⟶ 390:
This is a translation of the C example.
 
<langsyntaxhighlight lang="bracmat">1000000000:?MOD;
tbl$(state,55);
0:?si:?sj;
Line 243 ⟶ 441:
));
 
Main$;</langsyntaxhighlight>
 
{{out}}
Line 259 ⟶ 457:
=={{header|C}}==
This is basically the same as the reference C code, only differs in that it's C89.
<langsyntaxhighlight lang="c">#include<stdio.h>
 
#define MOD 1000000000
Line 301 ⟶ 499:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">
public class SubtractiveGenerator {
public static int MAX = 1000000000;
Line 344 ⟶ 542:
}
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 362 ⟶ 560:
=={{header|C++}}==
{{libheader|Boost}}
<langsyntaxhighlight lang="cpp">
// written for clarity not efficiency.
 
Line 426 ⟶ 624:
return 0;
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 440 ⟶ 638:
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(defn xpat2-with-seed
"produces an xpat2 function initialized from seed"
[seed]
Line 462 ⟶ 660:
 
(println (xpat2) (xpat2) (xpat2)) ; prints: 467478574 512932792 539453717
</syntaxhighlight>
</lang>
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">(defun sub-rand (state)
(let ((x (last state)) (y (last state 25)))
;; I take "circular buffer" very seriously (until some guru
Line 487 ⟶ 685:
;; test it (output same as everyone else's)
(let ((f (bentley-clever 292929)))
(dotimes (x 10) (format t "~a~%" (funcall f))))</langsyntaxhighlight>
 
=={{header|D}}==
{{trans|C}}
 
<langsyntaxhighlight lang="d">import std.stdio;
 
struct Subtractive {
Line 543 ⟶ 741:
foreach (i; 0 .. 10)
writeln(gen.subrand());
}</langsyntaxhighlight>
{{out}}
<pre>467478574
Line 557 ⟶ 755:
 
=={{header|dc}}==
<langsyntaxhighlight lang="dc">[*
* (seed) lsx --
* Seeds the subtractive generator.
Line 608 ⟶ 806:
lrx psz
lrx psz
lrx psz</langsyntaxhighlight>
 
This program prints 467478574, 512932792, 539453717.
 
This implementation never uses multiplication, but it does use modulus (remainder from division) to put each random number in range from 0 to 10^9 - 1.
 
=={{header|EasyLang}}==
{{trans|C}}
<syntaxhighlight>
MOD = 1000000000
len state[] 55
arrbase state[] 0
global si sj .
funcdecl subrand .
proc subrand_seed p1 . .
p2 = 1
state[0] = p1 mod MOD
j = 21
for i = 1 to 54
state[j] = p2
p2 = (p1 - p2) mod MOD
p1 = state[j]
j = (j + 21) mod 55
.
si = 0
sj = 24
for i = 0 to 164
h = subrand
h = h
.
.
func subrand .
if si = sj
subrand_seed 0
.
si = (si - 1) mod 55
sj = (sj - 1) mod 55
x = (state[si] - state[sj]) mod MOD
state[si] = x
return x
.
subrand_seed 292929
for i to 10
print subrand
.
</syntaxhighlight>
 
=={{header|Elixir}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="elixir">defmodule Subtractive do
def new(seed) when seed in 0..999_999_999 do
s = Enum.reduce(1..53, [1, seed], fn _,[a,b|_]=acc -> [b-a | acc] end)
Line 635 ⟶ 874:
 
Subtractive.new(292929)
for _ <- 1..10, do: IO.puts Subtractive.rand</langsyntaxhighlight>
 
{{out}}
Line 653 ⟶ 892:
=={{header|F_Sharp|F#}}==
<p>Similar to Haskell, using lazy evaluation.</p>
<langsyntaxhighlight lang="fsharp">[<EntryPoint>]
let main argv =
let m = 1000000000
Line 667 ⟶ 906:
r |> Seq.skip 220 |> Seq.take 3
|> Seq.iter (printfn "%d")
0</langsyntaxhighlight>
{{out}}
<pre>467478574
Line 675 ⟶ 914:
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
<langsyntaxhighlight lang="fortran">module subgenerator
implicit none
 
Line 730 ⟶ 969:
end do
end program</langsyntaxhighlight>
{{out}}
<pre>
Line 746 ⟶ 985:
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 845 ⟶ 1,084:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 854 ⟶ 1,093:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">subtractgen :: Int -> [Int]
subtractgen seed = drop 220 out
where
out = mmod $ r ++<> zipWith (-) out (drop 31 out)
where
r = take 55 $ shuffle $ cycle $ take 55 s
shuffle x = head(:) xx. :head <*> shuffle xx$ drop 34 x
where
xx = drop 34 x
s = mmod $ seed : 1 : zipWith (-) s (tail s)
mmod = mapfmap (`mod` 10 ^ 9)
 
main :: IO ()
main = mapM_ print $ take 10 $ subtractgen 292929</langsyntaxhighlight>
{{out}}
<pre>
Line 883 ⟶ 1,120:
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight Iconlang="icon">procedure main()
every 1 to 10 do
write(rand_sub(292929))
Line 908 ⟶ 1,145:
put(ring,get(ring))
return ring[-1]
end</langsyntaxhighlight>
 
{{out}}
Line 929 ⟶ 1,166:
Yes! '''f^:(-1)''' IS the inverse of '''f''' . When known.
 
<langsyntaxhighlight Jlang="j">came_from_locale_sg_=: coname''
cocurrent'sg' NB. install the state of rng sg into locale sg
 
Line 946 ⟶ 1,183:
cocurrent came_from_locale NB. return to previous locale
sg=: sg_sg_ NB. make a local name for sg in locale sg
</syntaxhighlight>
</lang>
 
Use:
<langsyntaxhighlight lang="sh">$ jconsole
load'sg.ijs'
sg 2
Line 956 ⟶ 1,193:
539453717 20349702 615542081 378707948
</syntaxhighlight>
</lang>
 
=={{header|Java}}==
Translation of [[Subtractive_generator#C|C]] via [[Subtractive_generator#D|D]]
{{works with|Java|8}}
<langsyntaxhighlight lang="java">import java.util.function.IntSupplier;
import static java.util.stream.IntStream.generate;
 
Line 1,013 ⟶ 1,250:
.forEach(System.out::println);
}
}</langsyntaxhighlight>
 
<pre>467478574
Line 1,025 ⟶ 1,262:
506003769
380969305</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
 
Note that `subrand` as defined here returns the object representing
the current state of the PRNG, with .x set to the most recent PRN.
 
Note also that because jq does not support forward declarations
except insofar as a subfunction may call its parent (or grandparent, etc),
we have defined `subrand` as an accessible subfunction of `subrandSeed`.
<syntaxhighlight lang="jq"># If $p is null, then call `subrand`,
# which sets .x as the PRN and which expects the the input to
# be the PRNG state, which is updated.
def subrandSeed($p):
 
def subrand:
if (.si == .sj) then subrandSeed(0) else . end
| .si |= (if . == 0 then 54 else . - 1 end)
| .sj |= (if . == 0 then 54 else . - 1 end)
| .mod as $mod
| .x = ((.state[.si] - .state[.sj]) | if . < 0 then . + $mod else . end)
| .state[.si] = .x ;
 
if $p == null then subrand
else
{mod: 1e9, state: [], si: 0, sj: 0, p: $p, p2: 1, j: 21}
| .state[0] = ($p % .mod)
| reduce range(1; 55) as $i (.;
if .j >= 55 then .j += -55 else . end
| .state[.j] = .p2
| .p2 = .p - .p2
| if .p2 < 0 then .p2 = .p2 + .mod else . end
| .p = .state[.j]
| .j += 21)
| .si = 0
| .sj = 24
| reduce range(1; 166) as $i (.; subrand)
end;
 
def subrand:
subrandSeed(null);
 
subrandSeed(292929)
| foreach range(0; 10) as $i (.;
subrand;
"r[\($i+220)] = \(.x)")</syntaxhighlight>
{{out}}
<pre>
r[220] = 467478574
r[221] = 512932792
r[222] = 539453717
r[223] = 20349702
r[224] = 615542081
r[225] = 378707948
r[226] = 933204586
r[227] = 824858649
r[228] = 506003769
r[229] = 380969305
</pre>
 
=={{header|Julia}}==
Line 1,030 ⟶ 1,328:
{{works with|Julia|1.0}}
 
<langsyntaxhighlight lang="julia">i,j,m,d,seed = 55,24,10^9,34,292929 # parameters
s = Array{Int32}(undef,i); r = similar(s)
s[1:2] = [seed,1] # table initialization
Line 1,045 ⟶ 1,343:
x = readline(stdin) # wait until the ENTER key is pressed
length(x) > 0 && break # any other key before ENTER => exit
end</langsyntaxhighlight>
{{out}}
<pre>(220, 467478574)
Line 1,063 ⟶ 1,361:
=={{header|Kotlin}}==
{{trans|C}}
<langsyntaxhighlight lang="scala">// version 1.1.51
 
const val MOD = 1_000_000_000
Line 1,102 ⟶ 1,400:
subrandSeed(292_929)
for (i in 0..9) println("r[${i + 220}] = ${subrand()}")
}</langsyntaxhighlight>
 
{{out}}
Line 1,118 ⟶ 1,416:
</pre>
 
=={{header|MathematicaLua}}==
<syntaxhighlight lang="lua">function SubGen(seed)
<lang Mathematica>initialize[n_] :=
local n, r, s = 54, {}, { [0]=seed, 1 }
for n = 2,54 do s[n] = (s[n-2] - s[n-1]) % 1e9 end
for n = 0,54 do r[n] = s[(34*(n+1))%55] end
local next = function()
n = (n+1) % 55
r[n] = (r[(n-55)%55] - r[(n-24)%55]) % 1e9
return r[n]
end
for n = 55,219 do next() end
return next
end
subgen = SubGen(292929)
for n = 220,229 do print(n,subgen()) end</syntaxhighlight>
{{out}}
<pre>220 467478574
221 512932792
222 539453717
223 20349702
224 615542081
225 378707948
226 933204586
227 824858649
228 506003769
229 380969305</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">initialize[n_] :=
Module[{buffer},
buffer =
Line 1,127 ⟶ 1,452:
nextValue[buffer_] :=
Flatten@{Rest@buffer, Mod[Subtract @@ buffer[[{1, 32}]], 10^9]}</langsyntaxhighlight>
 
<pre>buffer = initialize[292929];
Line 1,144 ⟶ 1,469:
 
</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">import deques, sequtils
 
template shfl(idx): untyped = (K*(idx+1)) mod I
 
func mutuallyprime(I, K: int16): bool {.compiletime.} =
## compile time check shuffling works properly
let
x = {1'i16..I}
s = x.toSeq
var r: set[int16]
for n in 0..<I:
r.incl s[n.shfl]
r == x
 
func `%`(i: int, m: int): int = (if i < 0: i+m else: i)
## positive modulo, and we don't need to test if > m
## because (i-j) is always less than m
 
template next(state): untyped =
state.addLast (state[^I]-state[^J]) % M
discard state.popFirst()
 
func seedGen[I, J, K, M: static int](seed: range[0..M-1]): Deque[int] =
var s = @[seed, 1]
for _ in 2..<I:
s.add (s[^2]-s[^1]) % M
#reorder and put into ring buffer
for i in 0..<I:
result.addLast s[i.shfl]
#cycle through the next 165 values
for _ in 0..<3*I:
result.next
 
func initSubGen[I, J, K, M: static int](seed: range[0..M-1]): auto =
##check parameters at compile time
##seed will be checked to be in the range 0..M-1
static:
for x in [I, J, K, M]:
assert x > 0, "all params must be positive"
assert I > J, "I must be > J"
assert mutuallyprime(I, K), "I, K must be relatively prime"
var r = seedGen[I, J, K, M](seed)
result = proc(): int =
r.next
r.peekLast
 
let subGen* = initSubGen[55, 24, 34, 1e9.int]
 
when isMainModule:
let rand = subGen(292929)
for _ in 1..3:
echo rand()</syntaxhighlight>
{{out}}
<pre>467478574
512932792
539453717</pre>
 
=={{header|OCaml}}==
{{trans|C}}
 
<langsyntaxhighlight lang="ocaml">let _mod = 1_000_000_000
let state = Array.create 55 0
let si = ref 0
Line 1,181 ⟶ 1,564:
let () =
subrand_seed 292929;
for i = 1 to 10 do Printf.printf "%d\n" (subrand()) done</langsyntaxhighlight>
 
{{out}}
Line 1,198 ⟶ 1,581:
=={{header|ooREXX}}==
{{trans|REXX}}
<langsyntaxhighlight lang="oorexx">/*REXX program uses a subtractive generaTor,and creates a sequence of ranDom numbers. */
/* array index must be positive! */
s=.array~new
Line 1,229 ⟶ 1,612:
mod: Procedure
Parse Arg a,b
Return ((a//b)+b)//b </langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>same as with REXX</pre>
 
=={{header|PARI/GP}}==
<langsyntaxhighlight lang="parigp">sgv=vector(55,i,random(10^9));sgi=1;
sg()=sgv[sgi=sgi%55+1]=(sgv[sgi]-sgv[(sgi+30)%55+1])%10^9</langsyntaxhighlight>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use 5.10.0;
use strict;
 
Line 1,263 ⟶ 1,646:
 
bentley_clever(292929);
say subrand() for (1 .. 10);</langsyntaxhighlight>
{{out}}
<pre>467478574
Line 1,274 ⟶ 1,657:
=={{header|Phix}}==
{{trans|C#}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>sequence state = repeat(0,55)
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
integer pos
<span style="color: #004080;">sequence</span> <span style="color: #000000;">state</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">55</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">pos</span>
constant MAX = 1e9
function cap(integer n)
<span style="color: #008080;">constant</span> <span style="color: #000000;">MAX</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1e9</span>
if n<0 then n += MAX end if
<span style="color: #008080;">function</span> <span style="color: #000000;">cap</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
return n
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">MAX</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">n</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
function next()
pos = mod(pos,55)+1
<span style="color: #008080;">function</span> <span style="color: #000000;">next</span><span style="color: #0000FF;">()</span>
integer temp = cap(state[pos]-state[mod(pos+30,55)+1])
<span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pos</span><span style="color: #0000FF;">,</span><span style="color: #000000;">55</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
state[pos] = temp
<span style="color: #004080;">integer</span> <span style="color: #000000;">temp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cap</span><span style="color: #0000FF;">(</span><span style="color: #000000;">state</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pos</span><span style="color: #0000FF;">]-</span><span style="color: #000000;">state</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pos</span><span style="color: #0000FF;">+</span><span style="color: #000000;">30</span><span style="color: #0000FF;">,</span><span style="color: #000000;">55</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
return temp
<span style="color: #000000;">state</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pos</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">temp</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">temp</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure init(integer seed)
sequence temp = repeat(0,55)
<span style="color: #008080;">procedure</span> <span style="color: #000000;">init</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">seed</span><span style="color: #0000FF;">)</span>
temp[1] = cap(seed)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">temp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">55</span><span style="color: #0000FF;">)</span>
temp[2] = 1
<span style="color: #000000;">temp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cap</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seed</span><span style="color: #0000FF;">)</span>
for i=3 to 55 do
<span style="color: #000000;">temp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
temp[i] = cap(temp[i-2]-temp[i-1])
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span> <span style="color: #008080;">to</span> <span style="color: #000000;">55</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">temp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cap</span><span style="color: #0000FF;">(</span><span style="color: #000000;">temp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]-</span><span style="color: #000000;">temp</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
for i=1 to 55 do
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
state[i] = temp[mod(34*i,55)+1]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">55</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">state</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">temp</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">34</span><span style="color: #0000FF;">*</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">55</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
pos = 55
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
for i=55 to 219 do
<span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">55</span>
{} = next()
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">55</span> <span style="color: #008080;">to</span> <span style="color: #000000;">219</span> <span style="color: #008080;">do</span>
end for
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">next</span><span style="color: #0000FF;">()</span>
end procedure
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
init(292929)
for i=220 to 222 do
<span style="color: #000000;">init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">292929</span><span style="color: #0000FF;">)</span>
printf(1,"%d: %d\n",{i,next()})
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">220</span> <span style="color: #008080;">to</span> <span style="color: #000000;">222</span> <span style="color: #008080;">do</span>
end for</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d: %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">next</span><span style="color: #0000FF;">()})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,319 ⟶ 1,705:
=={{header|PicoLisp}}==
Using a circular list (as a true "ring" buffer).
<langsyntaxhighlight PicoLisplang="picolisp">(setq
*Bentley (apply circ (need 55))
*Bentley2 (nth *Bentley 32) )
Line 1,336 ⟶ 1,722:
(when (lt0 (dec *Bentley (pop '*Bentley2)))
(inc *Bentley 1000000000) )
(pop '*Bentley) )</langsyntaxhighlight>
Test:
<langsyntaxhighlight PicoLisplang="picolisp">(subRandSeed 292929)
(do 7 (println (subRand)))</langsyntaxhighlight>
{{out}}
<pre>467478574
Line 1,350 ⟶ 1,736:
 
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">
<lang PL/I>
subtractive_generator: procedure options (main);
 
Line 1,382 ⟶ 1,768:
 
end subtractive_generator;
</syntaxhighlight>
</lang>
<pre>
Required 3 results:
Line 1,410 ⟶ 1,796:
The first 55 generated values are placed directly into their reordered slots in the ring.
An array object is used along with a rotating index object to simulate a ring.
<syntaxhighlight lang="powershell">
<lang PowerShell>
function Get-SubtractiveRandom ( [int]$Seed )
{
Line 1,457 ⟶ 1,843:
Get-SubtractiveRandom
Get-SubtractiveRandom
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,471 ⟶ 1,857:
Uses collections.deque as a ring buffer
 
<langsyntaxhighlight lang="python">
import collections
s= collections.deque(maxlen=55)
Line 1,514 ⟶ 1,900:
for i in xrange(5):
print "result = ", getnextr()
</syntaxhighlight>
</lang>
 
===Python: As a class within a module===
Python 2 and 3 compatable.
<langsyntaxhighlight lang="python">import collections
 
_ten2nine = 10**9
Line 1,540 ⟶ 1,926:
if __name__ == '__main__':
srand = Subtractive_generator()
print([srand() for i in range(5)])</langsyntaxhighlight>
 
{{out}}
<pre>[467478574, 512932792, 539453717, 20349702, 615542081]</pre>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="Quackery"> [ stack ] is randoms ( --> s )
 
' [ 292929 1 ]
53 times
[ dup -2 peek
over -1 peek
- 1000000000 mod
join ]
dup witheach
[ swap
i^ 34 * 1 - 55 mod
poke ]
randoms put
 
[ randoms take
behead over 30 peek
- 1000000000 mod
tuck join
randoms put ] is rand ( --> n )
 
165 times [ rand drop ]
 
10 times [ rand echo cr ]</syntaxhighlight>
 
{{out}}
 
<pre>467478574
512932792
539453717
20349702
615542081
378707948
933204586
824858649
506003769
380969305</pre>
 
=={{header|Racket}}==
<langsyntaxhighlight Racketlang="racket">#lang racket
(define (make-initial-state a-list max-i)
(for/fold ((state a-list))
Line 1,575 ⟶ 2,000:
;that returns a new random number each time it's called
(define rand (create-substractive-generator 292929))
(build-list 3 (lambda (_) (rand))) ;returns a list made from the 3 wanted numbers</langsyntaxhighlight>
 
=={{header|Raku}}==
Line 1,582 ⟶ 2,007:
{{works with|Rakudo|2018.03}}
 
<syntaxhighlight lang="raku" perl6line>sub bentley-clever($seed) {
constant $mod = 1_000_000_000;
my @seeds = ($seed % $mod, 1, (* - *) % $mod ... *)[^55];
Line 1,598 ⟶ 2,023:
 
my @sr = bentley-clever(292929);
.say for @sr[^10];</langsyntaxhighlight>
Here we just make the seeder return the random sequence as a lazy list.
 
Line 1,616 ⟶ 2,041:
{{trans|PL/I}}
 
Some optimization was done so that the first two &nbsp; '''do''' &nbsp; loops executed faster.
<lang rexx>/*REXX program uses a subtractive generator, and creates a sequence of random numbers. */
<syntaxhighlight lang="rexx">/*REXX program uses a subtractive generator, and creates a sequence of random numbers. */
s.0= 292929; s.1= 1; billion= 1e9 /* ◄────────┐ */
numeric digitss.0= 20292929; s.1= 1; billion= 10**9 /*same as─►─┘ */ billion= 1e9
numeric digits 20
cI= 55; do i=2 to cI-1
cI= 55; do i=2 for cI-2; s.i= mod( s(i-2) - s(i-1), billion)
end /*i*/
Cp= 34
do j=0 tofor cI-; r.j= s( mod( cP * (j+1), cI))
end r.j= s( mod( cP /* (j+1), cI))*/
end /*j*/
m= 219; Cj= 24
do k=cI to m; _= k // cI
r._= mod( r( mod(k-cI, cI)) - r( mod(k-cJ, cI) ), billion)
end /*km*/
t= 235
do n=m+1 to t; _= n // cI
r._= mod( r( mod(n-cI, cI)) - r( mod(n-cJ, cI) ), billion)
say right(r._, 40)
end /*n*/
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
mod: procedure; parse arg a,b; return ( (a // b) + b) // b
r: parse arg #; return r.#
s: parse arg #; return s.#</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Line 1,659 ⟶ 2,083:
563900213
</pre>
 
=={{header|RPL}}==
Here, most data manipulation is performed directly in the stack. This requires less code, but slows down execution: when handling large amounts of data in RPL, it is better to store them in array variables and perform operations directly on them.
{{works with|Halcyon Calc|4.2.7}}
{| class="wikitable"
! RPL code
! Comment
|-
|
≪ 1
2 54 '''START''' DUP2 - 1E9 MOD '''NEXT'''
55 →ARRY ''''SEEDS'''' STO
0 54 '''FOR''' j
''''SEEDS'''' j 1 + 34 * 55 MOD GET 1 + GET '''NEXT'''
55 →ARRY ''''SEEDS'''' STO
≫ ''''INITX'''' STO
'''SEEDS''' ARRY→ DROP
55 ROLL 25 PICK - 1E9 MOD
55 →ARRY ''''SEEDS'''' STO
≫ ''''XPAT2'''' STO
|
'''INITX''' ''( seed -- )''
calculate in stack s(n)=mod(s(n-2)-s(n-1),10^9) for 2≤n≤54
Store s(0)..s(54) as an array in SEEDS variable
for j=0 to 54
r(j) = s(mod(34*(j+1),55)) & keep it in stack
Store r(0)..r(54) as an array in SEEDS variable
'''XPAT2''' ''( -- )''
Put SEEDS in stack
r(n+1) = mod(r(n-55)-r(n-24),10^9)
Transfer stack to SEEDS
|}
{{in}}
<pre>
≪ 292929 INITX
55 222 START XPAT2 NEXT
220 222 FOR j SEEDS j GET NEXT
≫ EVAL
</pre>
{{out}}
<pre>
3: 467478574
2: 512932792
1: 539453717
</pre>
Runs in 97 seconds on a basic HP-28S
 
=={{header|Ruby}}==
This implementation aims for simplicity, not speed. <code>SubRandom#rand</code> pushes to and shifts from an array; this might be slower than a ring buffer. The seeding method must call <code>rand</code> 55 extra times (220 times instead of 165 times). The code also calls [[Arithmetic/Integer#Ruby|Ruby's modulus operator]], which always returns a non-negative integer if the modulus is positive.
 
<langsyntaxhighlight lang="ruby"># SubRandom is a subtractive random number generator which generates
# the same sequences as Bentley's generator, as used in xpat2.
class SubRandom
Line 1,699 ⟶ 2,174:
 
rng = SubRandom.new(292929)
p (1..3).map { rng.rand }</langsyntaxhighlight>
 
<pre>[467478574, 512932792, 539453717]</pre>
 
=={{header|Rust}}==
 
{{works with|Rust|2021}}
This implementation uses a ring buffer in the form of a <code>Vec<i32></code>. It is fully configurable, although the seeding algorithm is only implemented for a generator with i = 55, j = 24, and m = 10<sup>9</sup>.
Like C, Rust's <code>%</code> will give negative results for some negative parameters. This algorithm uses [https://doc.rust-lang.org/std/primitive.i32.html#method.rem_euclid the <code>i32::rem_euclid()</code> method] instead.
<syntaxhighlight lang="rust">struct SubtractiveGenerator {
/// m in the formula
modulo: i32,
/// i and j in the formula
offsets: (u32, u32),
/// r in the formula. It is used as a ring buffer.
state: Vec<i32>,
/// n in the formula
position: usize,
}
 
impl SubtractiveGenerator {
fn new(modulo: i32, first_offset: u32, second_offset: u32) -> Self {
// The state size has to fit into a usize to index state properly
// without overflow.
let state_size: usize = first_offset.try_into().unwrap();
 
// Both offsets have to fit in i32 for the substractions to work
// without overflow.
assert!(first_offset <= i32::MAX as u32);
assert!(first_offset > second_offset);
SubtractiveGenerator {
modulo,
offsets: (first_offset, second_offset),
state: Vec::with_capacity(state_size),
position: 0,
}
}
}
 
impl Iterator for SubtractiveGenerator {
type Item = i32;
 
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
let state_size = self.offsets.0 as usize;
 
assert_eq!(self.state.len(), state_size);
 
self.position = (self.position + 1) % self.offsets.0 as usize;
 
let i1 = (self.position as i32 - self.offsets.0 as i32).rem_euclid(state_size as i32);
let i2 = (self.position as i32 - self.offsets.1 as i32).rem_euclid(state_size as i32);
 
let p1 = self.state[i1 as usize];
let p2 = self.state[i2 as usize];
 
self.state[self.position] = (p1 - p2).rem_euclid(self.modulo);
 
Some(self.state[self.position])
}
}
 
/// Returns a pre-seeded subtractive generator, which generates the same
/// sequences as Bentley's generator, as used in xpat2.
fn get_seeded_xpat2_gen(seed: i32) -> SubtractiveGenerator {
let mut gen = SubtractiveGenerator::new(1_000_000_000, 55, 24);
 
let state_size = gen.offsets.0 as usize;
 
let mut pre_state = Vec::with_capacity(state_size);
pre_state.push(seed);
pre_state.push(1);
for i in 2..state_size {
pre_state.push((pre_state[i - 2] - pre_state[i - 1]).rem_euclid(gen.modulo));
}
 
for i in 0..state_size {
gen.state.push(pre_state[(34 * (i + 1)) % 55]);
}
 
gen.position = 54;
for _ in 0..165 {
gen.next();
}
 
gen
}
 
fn main() {
let gen = get_seeded_xpat2_gen(292929);
 
for n in gen.take(5) {
println!("{}", n);
}
}</syntaxhighlight>
<pre>467478574
512932792
539453717
20349702
615542081</pre>
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const integer: MOD is 1000000000;
Line 1,757 ⟶ 2,328:
writeln(subrand(gen));
end for;
end func;</langsyntaxhighlight>
 
{{out}}
Line 1,774 ⟶ 2,345:
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">class SubRandom(seed, state=[]) {
 
const mod = 1_000_000_000;
Line 1,795 ⟶ 2,366:
 
var r = SubRandom(292929);
10.times { say r.subrand };</langsyntaxhighlight>
{{out}}
<pre>
Line 1,812 ⟶ 2,383:
=={{header|Tcl}}==
{{trans|C}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
namespace eval subrand {
variable mod 1000000000 state [lrepeat 55 0] si 0 sj 0
Line 1,846 ⟶ 2,417:
for {set i 0} {$i < 10} {incr i} {
puts [subrand::gen]
}</langsyntaxhighlight>
 
=={{header|uBasic/4tHWren}}==
{{trans|C}}
<lang>Push 292929 : Gosub 100 : d = Pop()
<syntaxhighlight lang="wren">var mod = 1e9
var state = List.filled(55, 0)
var si = 0
var sj = 0
 
var subrand // forward declaration
For i = 1 To 10
Push 0 : Gosub 100
Print Pop()
Next
 
var subrandSeed = Fn.new { |p|
End
var p2 = 1
state[0] = p % mod
var j = 21
for (i in 1..54) {
if (j >= 55) j = j - 55
state[j] = p2
p2 = p - p2
if (p2 < 0) p2 = p2 + mod
p = state[j]
j = j + 21
}
si = 0
sj = 24
for (i in 1..165) subrand.call()
}
 
subrand = Fn.new {
100 s = Pop()
Ifif s(si == 0sj) ThensubrandSeed.call(0)
psi = (psi +== 10) %? 5554 : si - 1
sj = @(p)sj == @(p0) -? @((p54 +: 31)sj %- 55)1
var x = Ifstate[si] @(p)- < 0 Thenstate[sj]
if (x < 0) @(p)x = @(p)x + 1000000000mod
state[si] = Endifx
return x
Push (@(p)) : Return
}
Endif
 
subrandSeed.call(292929)
@(54) = s : @(33) = 1
for (i in 0..9) System.print("r[%(i+220)] = %(subrand.call())")</syntaxhighlight>
p = 12
 
For i = 2 To 54
@(p) = @((p + 42) % 55) - @((p + 21) % 55)
If @(p) < 0 Then
@(p) = @(p) + 1000000000
Endif
p = (p + 34) % 55
Next
 
For i = 55 To 219
Push 0 : Gosub 100 : d = Pop()
Next
 
Push 0 : Return</lang>
{{out}}
<pre>467478574
r[220] = 467478574
512932792
r[221] = 512932792
539453717
r[222] = 539453717
20349702
r[223] = 20349702
615542081
r[224] = 615542081
378707948
r[225] = 378707948
933204586
r[226] = 933204586
824858649
r[227] = 824858649
506003769
r[228] = 506003769
380969305
r[229] = 380969305
 
0 OK, 0:864
</pre>
 
Line 1,903 ⟶ 2,476:
{{trans|Python}}
{{trans|C}}
<langsyntaxhighlight lang="zkl">fcn rand_sub(x){
var ring=L(),m=(1e9).toInt();
mod:='wrap(n){ if(n<0) n+m else n };
Line 1,914 ⟶ 2,487:
ring.append((ring.pop(0)-ring[-24]):mod(_));
return(ring[-1]);
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">do(4){ println(rand_sub(292929)) } //seed ignored after first call</langsyntaxhighlight>
{{out}}
<pre>
9,479

edits