v2 / vlib / v / tests / bench / math_big_gcd / prime / maker.v
178 lines · 153 sloc · 3.62 KB · 8e35f4d9848f7ad35d857a187dddbfd2eca5e19d
Raw
1module prime
2
3import rand
4import toml
5import os
6
7pub const toml_path = 'vlib/v/tests/bench/math_big_gcd/primes.toml'
8
9pub interface DataI {
10 to_primeset() PrimeSet
11 from_primeset(PrimeSet) DataI
12}
13
14pub fn (di DataI) cast[T]() DataI {
15 return T{}.from_primeset(di.to_primeset())
16}
17
18pub type PrimeCfg = PrimeSet
19
20pub fn (pc PrimeCfg) short() string {
21 return "r: '${pc.r}' a: '${pc.a}' b: '${pc.b}'"
22}
23
24@[heap]
25pub struct PrimeSet {
26pub mut:
27 r string @[required]
28 a string @[required]
29 b string @[required]
30}
31
32pub fn (p PrimeSet) to_primeset() PrimeSet {
33 return p
34}
35
36pub fn (p PrimeSet) from_primeset(ps PrimeSet) DataI {
37 return ps
38}
39
40pub fn (p PrimeSet) predicate(pred fn (data PrimeSet) bool) bool {
41 return pred(p)
42}
43
44pub fn (p PrimeSet) key() string {
45 return [p.r, p.a, p.b].join('.')
46}
47
48pub fn (p PrimeSet) str() string {
49 return [p.r, p.a, p.b].join(' ')
50}
51
52fn extract_count(s string) int {
53 digits := '0123456789'.split('')
54 if s == '' || !s.split('').any(it in digits) {
55 return 0
56 }
57 ds := s.split('').filter(it in digits)
58 return ds.join('').int()
59}
60
61// sizes lists the available names for prime-number sections.
62pub fn sizes() []string {
63 primes := read_toml_file()
64 return primes.keys()
65}
66
67// usage returns section-names and the count of available primes
68//
69pub fn usage() string {
70 primes := read_toml_file()
71 return sizes().map('${it}[..${primes[it].len}]').join('\n\t')
72}
73
74// reads the Map[string] []string from disk
75// and returns the parsed content
76fn read_toml_file() map[string][]string {
77 fp := os.join_path(@VEXEROOT, toml_path)
78
79 tm_doc := toml.parse_file(fp) or {
80 err_msg := 'expected ${fp}'
81 eprintln(err_msg)
82 panic(err)
83 }
84 // TODO: what happens if this goes wrong ?
85 tm_primes := tm_doc.value('primes') as map[string]toml.Any
86
87 msg := 'expected a map[string][]string in TOML-data ? corrupt ?'
88 mut p := map[string][]string{}
89 for k in tm_primes.keys() {
90 p[k] = []string{}
91 arr := tm_primes[k] or { panic(msg) }
92 for _, elem in arr.array() {
93 p[k] << elem as string
94 }
95 }
96 return p
97}
98
99pub fn random_list(cfg []string) []string {
100 primes := read_toml_file()
101
102 mut p_list := []string{}
103 match cfg.len {
104 1 { // prime-size e.g. 'xs' given
105 if cfg[0] !in primes {
106 return p_list
107 } else {
108 return primes[cfg[0]]
109 }
110 }
111 2 { // prime-size and limiter given e.g 'xs.15'
112 prime_size := cfg[0]
113 if prime_size !in primes {
114 return p_list
115 }
116
117 mut prime_count := extract_count(cfg[1])
118 if prime_count == 0 {
119 return primes[prime_size]
120 }
121 mut num := ''
122 for prime_count != 0 {
123 num = primes[prime_size][rand.int_in_range(0, primes[prime_size].len - 1) or { 0 }]
124 if num in p_list {
125 continue
126 }
127 p_list << num
128 prime_count -= 1
129 if prime_count >= primes[prime_size].len {
130 p_list = primes[prime_size]
131 break
132 }
133 } // eo-for
134 return p_list
135 } // cfg not understood
136 else {
137 return p_list
138 }
139 }
140
141 return p_list
142}
143
144pub fn random_set(cfg PrimeCfg) ![]v.tests.bench.math_big_gcd.prime.PrimeSet {
145 p_lists := [
146 cfg.r.split('.'),
147 cfg.a.split('.'),
148 cfg.b.split('.'),
149 ].map(random_list(it.map(it.trim_space().to_lower_ascii())))
150
151 // test for empty lists
152 //
153 if p_lists.any(it.len == 0) {
154 msg := [
155 'bad config was :\n\n"${cfg}"',
156 "maybe try e.g { r: 'l.5' a: 'xxl.5 b: 'xl.10' } makes a set of 250",
157 'your config was { ${cfg.short()} }',
158 'sizes ${usage()}\n',
159 ].join('\n\n')
160
161 return error(msg)
162 }
163 // filter unique combinations thru map
164 //
165 mut tmp := map[string]PrimeSet{}
166 for r in p_lists[0] {
167 for a in p_lists[1] {
168 for b in p_lists[2] {
169 d := PrimeSet{r, a, b}
170 if d.key() in tmp {
171 continue
172 }
173 tmp[d.key()] = d
174 }
175 }
176 }
177 return tmp.keys().map(tmp[it])
178}
179