spec/math/random/rand.bend
bend-collections-laws-crypto@1.0.0.0 · 116 lines · 12 definitions
1import Base
2import bend-collections-laws-crypto@1.0.0.0/spec/lib/common.bend as C
3import bend-collections-laws-crypto@1.0.0.0/src/math/u64.bend as W
4import bend-collections-laws-crypto@1.0.0.0/spec/math/w64.bend as SW
5import bend-collections-laws-crypto@1.0.0.0/spec/math/random/source.bend as SRC
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31def b2n(b: Bool) -> Nat:
32 match b:
33 case True{}:
34 1n
35 case False{}:
36 0n
37
38def and_bits(w: Nat, +a: Nat, +b: Nat) -> Nat:
39 match w:
40 case 0n:
41 0n
42 case 1n+k:
43 Nat.add(Nat.mul(C.bit(a), C.bit(b)), Nat.double(and_bits(k, C.half(a), C.half(b))))
44
45def pow2mod(w: Nat, +n: Nat) -> Nat:
46 match w:
47 case 0n:
48 Nat.mod(1n, n)
49 case 1n+k:
50 Nat.mod(Nat.double(pow2mod(k, n)), n)
51
52def accept(+hi: Nat, ok: Bool) -> Maybe<&2, Nat>:
53 match ok:
54 case True{}:
55 Some{hi}
56 case False{}:
57 None{}
58
59
60def lemire(+w: Nat, +n: Nat, +hi: Nat, +lo: Nat) -> Maybe<&2, Nat>:
61 accept(hi, Bool.not(Bool.and(Nat.is_lt(lo, n), Nat.is_lt(lo, pow2mod(w, n)))))
62
63def draw_pos(+w: Nat, +x: Nat, +n: Nat, +m: Nat, pow2: Bool) -> Maybe<&2, Nat>:
64 match pow2:
65 case True{}:
66 Some{and_bits(w, x, m)}
67 case False{}:
68 lemire(w, n, C.high(w, Nat.mul(x, n)), C.low(w, Nat.mul(x, n)))
69
70def draw(+w: Nat, +x: Nat, n: Nat) -> Maybe<&2, Nat>:
71 match n:
72 case 0n:
73 Some{x}
74 case 1n+ +m:
75 draw_pos(w, x, 1n+m, m, Nat.is_eq(and_bits(w, 1n+m, m), 0n))
76
77def hit(m: Maybe<&2, Nat>, +k: Nat) -> Nat:
78 match m:
79 case None{}:
80 0n
81 case Some{v}:
82 b2n(Nat.is_eq(v, k))
83
84
85def count(+w: Nat, +n: Nat, +k: Nat, N: Nat) -> Nat:
86 match N:
87 case 0n:
88 0n
89 case 1n+ +x:
90 Nat.add(count(w, n, k, x), hit(draw(w, x, n), k))
91
92
93
94
95
96def below_go(~S: Data, ~next: S -> W.U64 & S, fuel: Nat, +n: Nat, m: Maybe<&2, Nat>, +x: Nat, +s: S) -> Nat & S:
97 match fuel m:
98 case 0n Some{k}:
99 (k, s)
100 case 0n None{}:
101 (C.high(64n, Nat.mul(x, n)), s)
102 case 1n+f Some{k}:
103 (k, s)
104 case 1n+f None{}:
105 below_go(~S, ~next, f, n, draw(64n, SW.value(SRC.fst64(S, next(s))), n), SW.value(SRC.fst64(S, next(s))), SRC.snd64(S, next(s)))
106
107
108def below(~S: Data, ~next: S -> W.U64 & S, fuel: Nat, +n: Nat, +s: S) -> Nat & S:
109 below_go(~S, ~next, fuel, n, draw(64n, SW.value(SRC.fst64(S, next(s))), n), SW.value(SRC.fst64(S, next(s))), SRC.snd64(S, next(s)))
110
111def occurrences(~A: Data, ~V: Data, ~rel: A -> V -> Bool, +v: V, xs: List<&2, A>) -> Nat:
112 match xs:
113 case Nil{}:
114 0n
115 case Con{+x, rest}:
116 Nat.add(b2n(rel(x, v)), occurrences(~A, ~V, ~rel, v, rest))