Subtractive generator: Difference between revisions
m
→{{header|Wren}}: Changed to Wren S/H
m (→{{header|Wren}}: Changed to Wren S/H) |
|||
(20 intermediate revisions by 14 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:
<
type State is private;
procedure Initialize (Generator : in out State; Seed : Natural);
Line 50 ⟶ 90:
Last : Natural;
end record;
end Subtractive_Generator;</
subtractive_generator.adb:
<
procedure Initialize (Generator : in out State; Seed : Natural) is
Line 85 ⟶ 125:
end Next;
end Subtractive_Generator;</
Example main.adb:
<
with Subtractive_Generator;
Line 101 ⟶ 141:
Ada.Text_IO.Put_Line (Integer'Image (I) & ":" & Integer'Image (N));
end loop;
end Main;</
{{out}}
Line 110 ⟶ 150:
=={{header|AutoHotkey}}==
{{works with|AutoHotkey_L}}
<
Loop, 10
Line 134 ⟶ 174:
, r[i] := Mod(r[i] - r[Mod(A_Index + 30, 55)], r["m"])
return, r
}</
{{out}}
<pre>220: 467478574
Line 147 ⟶ 187:
229: 380969305</pre>
=={{header|
==={{header|BBC BASIC}}===
{{works with|BBC BASIC for Windows}}
<
FOR i% = 1 TO 10
PRINT FNsubrand(0)
Line 174 ⟶ 215:
IF FNsubrand(0)
NEXT
= 0</
{{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.
<
tbl$(state,55);
0:?si:?sj;
Line 243 ⟶ 441:
));
Main$;</
{{out}}
Line 259 ⟶ 457:
=={{header|C}}==
This is basically the same as the reference C code, only differs in that it's C89.
<
#define MOD 1000000000
Line 301 ⟶ 499:
return 0;
}</
=={{header|C sharp|C#}}==
<
public class SubtractiveGenerator {
public static int MAX = 1000000000;
Line 344 ⟶ 542:
}
}
</syntaxhighlight>
{{out}}
Line 362 ⟶ 560:
=={{header|C++}}==
{{libheader|Boost}}
<
// written for clarity not efficiency.
Line 426 ⟶ 624:
return 0;
}
</syntaxhighlight>
{{out}}
Line 440 ⟶ 638:
=={{header|Clojure}}==
<
"produces an xpat2 function initialized from seed"
[seed]
Line 462 ⟶ 660:
(println (xpat2) (xpat2) (xpat2)) ; prints: 467478574 512932792 539453717
</syntaxhighlight>
=={{header|Common Lisp}}==
<
(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))))</
=={{header|D}}==
{{trans|C}}
<
struct Subtractive {
Line 543 ⟶ 741:
foreach (i; 0 .. 10)
writeln(gen.subrand());
}</
{{out}}
<pre>467478574
Line 557 ⟶ 755:
=={{header|dc}}==
<
* (seed) lsx --
* Seeds the subtractive generator.
Line 608 ⟶ 806:
lrx psz
lrx psz
lrx psz</
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}}
<
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</
{{out}}
Line 653 ⟶ 892:
=={{header|F_Sharp|F#}}==
<p>Similar to Haskell, using lazy evaluation.</p>
<
let main argv =
let m = 1000000000
Line 667 ⟶ 906:
r |> Seq.skip 220 |> Seq.take 3
|> Seq.iter (printfn "%d")
0</
{{out}}
<pre>467478574
Line 675 ⟶ 914:
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
<
implicit none
Line 730 ⟶ 969:
end do
end program</
{{out}}
<pre>
Line 746 ⟶ 985:
=={{header|Go}}==
<
import (
Line 845 ⟶ 1,084:
}
}
}</
{{out}}
<pre>
Line 854 ⟶ 1,093:
=={{header|Haskell}}==
<
subtractgen seed = drop 220 out
where
out = mmod $ r
where
r = take 55 $ shuffle $ cycle $ take 55 s
shuffle x =
s = mmod $ seed : 1 : zipWith (-) s (tail s)
mmod =
main :: IO ()
main = mapM_ print $ take 10 $ subtractgen 292929</
{{out}}
<pre>
Line 883 ⟶ 1,120:
=={{header|Icon}} and {{header|Unicon}}==
<
every 1 to 10 do
write(rand_sub(292929))
Line 908 ⟶ 1,145:
put(ring,get(ring))
return ring[-1]
end</
{{out}}
Line 929 ⟶ 1,166:
Yes! '''f^:(-1)''' IS the inverse of '''f''' . When known.
<
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>
Use:
<
load'sg.ijs'
sg 2
Line 956 ⟶ 1,193:
539453717 20349702 615542081 378707948
</syntaxhighlight>
=={{header|Java}}==
Translation of [[Subtractive_generator#C|C]] via [[Subtractive_generator#D|D]]
{{works with|Java|8}}
<
import static java.util.stream.IntStream.generate;
Line 1,013 ⟶ 1,250:
.forEach(System.out::println);
}
}</
<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}}
<
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</
{{out}}
<pre>(220, 467478574)
Line 1,063 ⟶ 1,361:
=={{header|Kotlin}}==
{{trans|C}}
<
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()}")
}</
{{out}}
Line 1,119 ⟶ 1,417:
=={{header|Lua}}==
<
local n, r, s = 54, {}, { [0]=seed, 1 }
for n = 2,54 do s[n] = (s[n-2] - s[n-1]) % 1e9 end
Line 1,132 ⟶ 1,430:
end
subgen = SubGen(292929)
for n = 220,229 do print(n,subgen()) end</
{{out}}
<pre>220 467478574
Line 1,145 ⟶ 1,443:
229 380969305</pre>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
Module[{buffer},
buffer =
Line 1,154 ⟶ 1,452:
nextValue[buffer_] :=
Flatten@{Rest@buffer, Mod[Subtract @@ buffer[[{1, 32}]], 10^9]}</
<pre>buffer = initialize[292929];
Line 1,171 ⟶ 1,469:
</pre>
=={{header|Nim}}==
<
template shfl(idx): untyped = (K*(idx+1)) mod I
func mutuallyprime(I, K: int16): bool {.compiletime.} =
## compile time check shuffling works properly
let
Line 1,210 ⟶ 1,511:
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 =
Line 1,221 ⟶ 1,522:
let rand = subGen(292929)
for _ in 1..3:
echo rand()</
{{out}}
<pre>467478574
Line 1,230 ⟶ 1,531:
{{trans|C}}
<
let state = Array.create 55 0
let si = ref 0
Line 1,263 ⟶ 1,564:
let () =
subrand_seed 292929;
for i = 1 to 10 do Printf.printf "%d\n" (subrand()) done</
{{out}}
Line 1,280 ⟶ 1,581:
=={{header|ooREXX}}==
{{trans|REXX}}
<
/* array index must be positive! */
s=.array~new
Line 1,311 ⟶ 1,612:
mod: Procedure
Parse Arg a,b
Return ((a//b)+b)//b </
{{out|output|text= when using the default input:}}
<pre>same as with REXX</pre>
=={{header|PARI/GP}}==
<
sg()=sgv[sgi=sgi%55+1]=(sgv[sgi]-sgv[(sgi+30)%55+1])%10^9</
=={{header|Perl}}==
<
use strict;
Line 1,345 ⟶ 1,646:
bentley_clever(292929);
say subrand() for (1 .. 10);</
{{out}}
<pre>467478574
Line 1,356 ⟶ 1,657:
=={{header|Phix}}==
{{trans|C#}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<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>
<span style="color: #008080;">constant</span> <span style="color: #000000;">MAX</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1e9</span>
<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>
<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>
<span style="color: #008080;">return</span> <span style="color: #000000;">n</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">next</span><span style="color: #0000FF;">()</span>
<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>
<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>
<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>
<span style="color: #008080;">return</span> <span style="color: #000000;">temp</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<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>
<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>
<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>
<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>
<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>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<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>
<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>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">55</span>
<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>
<span style="color: #0000FF;">{}</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>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">292929</span><span style="color: #0000FF;">)</span>
<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>
<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,401 ⟶ 1,705:
=={{header|PicoLisp}}==
Using a circular list (as a true "ring" buffer).
<
*Bentley (apply circ (need 55))
*Bentley2 (nth *Bentley 32) )
Line 1,418 ⟶ 1,722:
(when (lt0 (dec *Bentley (pop '*Bentley2)))
(inc *Bentley 1000000000) )
(pop '*Bentley) )</
Test:
<
(do 7 (println (subRand)))</
{{out}}
<pre>467478574
Line 1,432 ⟶ 1,736:
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">
subtractive_generator: procedure options (main);
Line 1,464 ⟶ 1,768:
end subtractive_generator;
</syntaxhighlight>
<pre>
Required 3 results:
Line 1,492 ⟶ 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">
function Get-SubtractiveRandom ( [int]$Seed )
{
Line 1,539 ⟶ 1,843:
Get-SubtractiveRandom
Get-SubtractiveRandom
</syntaxhighlight>
{{out}}
<pre>
Line 1,553 ⟶ 1,857:
Uses collections.deque as a ring buffer
<
import collections
s= collections.deque(maxlen=55)
Line 1,596 ⟶ 1,900:
for i in xrange(5):
print "result = ", getnextr()
</syntaxhighlight>
===Python: As a class within a module===
Python 2 and 3 compatable.
<
_ten2nine = 10**9
Line 1,622 ⟶ 1,926:
if __name__ == '__main__':
srand = Subtractive_generator()
print([srand() for i in range(5)])</
{{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}}==
<
(define (make-initial-state a-list max-i)
(for/fold ((state a-list))
Line 1,657 ⟶ 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</
=={{header|Raku}}==
Line 1,664 ⟶ 2,007:
{{works with|Rakudo|2018.03}}
<syntaxhighlight lang="raku"
constant $mod = 1_000_000_000;
my @seeds = ($seed % $mod, 1, (* - *) % $mod ... *)[^55];
Line 1,680 ⟶ 2,023:
my @sr = bentley-clever(292929);
.say for @sr[^10];</
Here we just make the seeder return the random sequence as a lazy list.
Line 1,698 ⟶ 2,041:
{{trans|PL/I}}
Some optimization was done so that the first two '''do''' loops executed faster.
<syntaxhighlight lang="rexx">/*REXX program uses a subtractive generator, and creates a sequence of random numbers. */
numeric digits 20
cI= 55; do i=2 for cI-2; s.i= mod( s(i-2)
Cp= 34
end
m= 219; Cj= 24
t= 235
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
mod: procedure;
r:
s:
{{out|output|text= when using the default input:}}
<pre>
Line 1,741 ⟶ 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.
<
# the same sequences as Bentley's generator, as used in xpat2.
class SubRandom
Line 1,781 ⟶ 2,174:
rng = SubRandom.new(292929)
p (1..3).map { rng.rand }</
<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}}==
<
const integer: MOD is 1000000000;
Line 1,839 ⟶ 2,328:
writeln(subrand(gen));
end for;
end func;</
{{out}}
Line 1,856 ⟶ 2,345:
=={{header|Sidef}}==
<
const mod = 1_000_000_000;
Line 1,877 ⟶ 2,366:
var r = SubRandom(292929);
10.times { say r.subrand };</
{{out}}
<pre>
Line 1,894 ⟶ 2,383:
=={{header|Tcl}}==
{{trans|C}}
<
namespace eval subrand {
variable mod 1000000000 state [lrepeat 55 0] si 0 sj 0
Line 1,928 ⟶ 2,417:
for {set i 0} {$i < 10} {incr i} {
puts [subrand::gen]
}</
=={{header|Wren}}==
{{trans|C}}
<
var state = List.filled(55, 0)
var si = 0
Line 2,018 ⟶ 2,456:
subrandSeed.call(292929)
for (i in 0..9) System.print("r[%(i+220)] = %(subrand.call())")</
{{out}}
Line 2,038 ⟶ 2,476:
{{trans|Python}}
{{trans|C}}
<
var ring=L(),m=(1e9).toInt();
mod:='wrap(n){ if(n<0) n+m else n };
Line 2,049 ⟶ 2,487:
ring.append((ring.pop(0)-ring[-24]):mod(_));
return(ring[-1]);
}</
<
{{out}}
<pre>
|