mt-lang 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/docs/index.html +4 -3
- data/lib/milk_tea/base.rb +1 -1
- data/std/asset_pack.mt +267 -0
- data/std/async/libuv_runtime.mt +539 -0
- data/std/async/mailbox.mt +191 -0
- data/std/async/runtime.mt +87 -0
- data/std/async.mt +87 -0
- data/std/base64.mt +185 -0
- data/std/behavior_tree.mt +396 -0
- data/std/binary.mt +314 -0
- data/std/binary_heap.mt +157 -0
- data/std/bitset.mt +239 -0
- data/std/box2d.mt +535 -0
- data/std/bytes.mt +46 -0
- data/std/c/box2d.mt +1254 -0
- data/std/c/cgltf.mt +647 -0
- data/std/c/cjson.mt +106 -0
- data/std/c/crypto.mt +11 -0
- data/std/c/crypto_support.h +51 -0
- data/std/c/ctype.mt +19 -0
- data/std/c/ctype_bindgen.h +29 -0
- data/std/c/curl.mt +1223 -0
- data/std/c/enet.mt +473 -0
- data/std/c/errno.mt +41 -0
- data/std/c/errno_bindgen.h +53 -0
- data/std/c/flecs.mt +2945 -0
- data/std/c/fs.linux.mt +43 -0
- data/std/c/fs.windows.mt +43 -0
- data/std/c/fs_support.h +954 -0
- data/std/c/gl.mt +2065 -0
- data/std/c/gl_registry_helpers.h +10748 -0
- data/std/c/glfw.mt +499 -0
- data/std/c/libc.mt +167 -0
- data/std/c/libuv.mt +1491 -0
- data/std/c/math.mt +22 -0
- data/std/c/math_bindgen.h +31 -0
- data/std/c/miniaudio.mt +3420 -0
- data/std/c/pcre2.mt +735 -0
- data/std/c/process.mt +58 -0
- data/std/c/process_support.h +1147 -0
- data/std/c/raygui.mt +1602 -0
- data/std/c/raylib.mt +1245 -0
- data/std/c/raymath.mt +163 -0
- data/std/c/rlgl.mt +434 -0
- data/std/c/rpng.mt +60 -0
- data/std/c/rres.mt +187 -0
- data/std/c/sdl3.mt +4132 -0
- data/std/c/sqlite3.mt +951 -0
- data/std/c/stb_image.mt +52 -0
- data/std/c/stb_image_resize2.mt +128 -0
- data/std/c/stb_image_write.mt +19 -0
- data/std/c/stb_rect_pack.mt +38 -0
- data/std/c/stb_truetype.mt +175 -0
- data/std/c/stb_vorbis.mt +31 -0
- data/std/c/stdio.mt +90 -0
- data/std/c/steamworks.h +5769 -0
- data/std/c/steamworks.mt +4771 -0
- data/std/c/string.mt +16 -0
- data/std/c/string_bindgen.h +36 -0
- data/std/c/sync.mt +33 -0
- data/std/c/sync_support.h +219 -0
- data/std/c/terminal.mt +24 -0
- data/std/c/terminal_support.h +408 -0
- data/std/c/time.mt +26 -0
- data/std/c/tls.mt +24 -0
- data/std/c/tls_support.h +626 -0
- data/std/c/tracy.mt +53 -0
- data/std/c/zlib.mt +20 -0
- data/std/c/zlib_support.h +239 -0
- data/std/c/zstd.mt +231 -0
- data/std/cell.mt +60 -0
- data/std/cgltf.mt +115 -0
- data/std/cjson.mt +90 -0
- data/std/cli.mt +768 -0
- data/std/cookie.mt +198 -0
- data/std/counter.mt +160 -0
- data/std/crypto.mt +74 -0
- data/std/cstring.mt +13 -0
- data/std/ctype.mt +52 -0
- data/std/curl/runtime.mt +261 -0
- data/std/curl.mt +38 -0
- data/std/deque.mt +348 -0
- data/std/encoding.mt +93 -0
- data/std/enet.mt +133 -0
- data/std/env.mt +41 -0
- data/std/errno.mt +47 -0
- data/std/flecs.mt +978 -0
- data/std/fmt.mt +271 -0
- data/std/fs.linux.mt +696 -0
- data/std/fs.windows.mt +711 -0
- data/std/fsm.mt +267 -0
- data/std/gl.mt +2062 -0
- data/std/glfw.mt +471 -0
- data/std/goap.mt +342 -0
- data/std/graph.mt +521 -0
- data/std/gzip.mt +77 -0
- data/std/hash.mt +429 -0
- data/std/http/server.mt +810 -0
- data/std/http.mt +1227 -0
- data/std/intern.mt +53 -0
- data/std/jobs.mt +288 -0
- data/std/json.mt +627 -0
- data/std/libc.mt +34 -0
- data/std/libuv.mt +554 -0
- data/std/linear_algebra.mt +243 -0
- data/std/linked_map.mt +372 -0
- data/std/linked_map_view.mt +49 -0
- data/std/linked_set.mt +117 -0
- data/std/log.mt +69 -0
- data/std/map.mt +418 -0
- data/std/math.mt +24 -0
- data/std/mem/arena.mt +137 -0
- data/std/mem/endian.mt +51 -0
- data/std/mem/heap.mt +298 -0
- data/std/mem/pool.mt +164 -0
- data/std/mem/stack.mt +47 -0
- data/std/mem/tracking.mt +119 -0
- data/std/miniaudio.mt +1299 -0
- data/std/multiset.mt +191 -0
- data/std/net/channel.mt +727 -0
- data/std/net/clock.mt +237 -0
- data/std/net/discovery.mt +277 -0
- data/std/net/lobby.mt +813 -0
- data/std/net/manager.mt +539 -0
- data/std/net/mux.mt +839 -0
- data/std/net/nat.mt +122 -0
- data/std/net/packet.mt +219 -0
- data/std/net/punch.mt +162 -0
- data/std/net/rpc.mt +119 -0
- data/std/net/session.mt +1157 -0
- data/std/net/stun.mt +252 -0
- data/std/net/sync.mt +183 -0
- data/std/net/turn.mt +459 -0
- data/std/net.mt +2944 -0
- data/std/oauth2.mt +408 -0
- data/std/option.mt +51 -0
- data/std/ordered_map.mt +497 -0
- data/std/ordered_set.mt +348 -0
- data/std/path.mt +368 -0
- data/std/pcre2/runtime.mt +35 -0
- data/std/pcre2.mt +78 -0
- data/std/priority_queue.mt +55 -0
- data/std/process.mt +837 -0
- data/std/queue.mt +55 -0
- data/std/random.mt +146 -0
- data/std/raygui.mt +99 -0
- data/std/raylib/debug_console.mt +71 -0
- data/std/raylib/easing.mt +388 -0
- data/std/raylib/packed_assets.mt +255 -0
- data/std/raylib/runtime.mt +30 -0
- data/std/raylib/tracy_gpu.mt +37 -0
- data/std/raylib.mt +1510 -0
- data/std/raymath.mt +153 -0
- data/std/result.mt +89 -0
- data/std/rlgl.mt +268 -0
- data/std/rpng.mt +46 -0
- data/std/rres.mt +36 -0
- data/std/sdl3/runtime.mt +54 -0
- data/std/sdl3.mt +1731 -0
- data/std/serialize.mt +68 -0
- data/std/set.mt +124 -0
- data/std/spatial.mt +176 -0
- data/std/sqlite3.mt +151 -0
- data/std/stack.mt +55 -0
- data/std/stb_image.mt +47 -0
- data/std/stb_image_resize2.mt +41 -0
- data/std/stb_image_write.mt +17 -0
- data/std/stb_rect_pack.mt +15 -0
- data/std/stb_truetype.mt +77 -0
- data/std/stb_vorbis.mt +16 -0
- data/std/stdio.mt +88 -0
- data/std/steamworks.mt +1542 -0
- data/std/str.mt +293 -0
- data/std/string.mt +234 -0
- data/std/sync.mt +194 -0
- data/std/tar.mt +704 -0
- data/std/terminal.mt +1002 -0
- data/std/testing.mt +266 -0
- data/std/thread.mt +120 -0
- data/std/time.mt +105 -0
- data/std/tls.mt +616 -0
- data/std/toml.mt +1310 -0
- data/std/tracy.mt +42 -0
- data/std/uri.mt +118 -0
- data/std/url.mt +372 -0
- data/std/vec.mt +433 -0
- data/std/zstd.mt +94 -0
- metadata +187 -2
data/std/graph.mt
ADDED
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
import std.vec as vec
|
|
2
|
+
import std.deque as deque
|
|
3
|
+
import std.mem.heap as heap
|
|
4
|
+
|
|
5
|
+
public struct Edge:
|
|
6
|
+
from: ptr_uint
|
|
7
|
+
to: ptr_uint
|
|
8
|
+
weight: float
|
|
9
|
+
|
|
10
|
+
public struct Graph[T]:
|
|
11
|
+
nodes: vec.Vec[T]
|
|
12
|
+
edges: vec.Vec[Edge]
|
|
13
|
+
is_directed: bool
|
|
14
|
+
|
|
15
|
+
public struct DenseGraph[T]:
|
|
16
|
+
nodes: vec.Vec[T]
|
|
17
|
+
offsets: vec.Vec[ptr_uint]
|
|
18
|
+
targets: vec.Vec[ptr_uint]
|
|
19
|
+
weights: vec.Vec[float]
|
|
20
|
+
is_directed: bool
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
extending Graph[T]:
|
|
24
|
+
public static function create() -> Graph[T]:
|
|
25
|
+
return Graph[T](
|
|
26
|
+
nodes = vec.Vec[T].create(),
|
|
27
|
+
edges = vec.Vec[Edge].create(),
|
|
28
|
+
is_directed = false
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
public static function create_directed() -> Graph[T]:
|
|
33
|
+
return Graph[T](
|
|
34
|
+
nodes = vec.Vec[T].create(),
|
|
35
|
+
edges = vec.Vec[Edge].create(),
|
|
36
|
+
is_directed = true
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
public function node_count() -> ptr_uint:
|
|
41
|
+
return this.nodes.len()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
public function edge_count() -> ptr_uint:
|
|
45
|
+
return this.edges.len()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
public editable function add_node(value: T) -> ptr_uint:
|
|
49
|
+
let index = this.nodes.len()
|
|
50
|
+
this.nodes.push(value)
|
|
51
|
+
return index
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
public function get_node(index: ptr_uint) -> T:
|
|
55
|
+
let node_ptr = this.nodes.get(index) else:
|
|
56
|
+
fatal(c"graph.get_node: index out of bounds")
|
|
57
|
+
return unsafe: read(node_ptr)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
public editable function add_edge(from: ptr_uint, to: ptr_uint):
|
|
61
|
+
this.add_weighted_edge(from, to, 1.0)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
public editable function add_weighted_edge(from: ptr_uint, to: ptr_uint, weight: float):
|
|
65
|
+
var e = zero[Edge]
|
|
66
|
+
e.from = from
|
|
67
|
+
e.to = to
|
|
68
|
+
e.weight = weight
|
|
69
|
+
this.edges.push(e)
|
|
70
|
+
if not this.is_directed:
|
|
71
|
+
var rev = zero[Edge]
|
|
72
|
+
rev.from = to
|
|
73
|
+
rev.to = from
|
|
74
|
+
rev.weight = weight
|
|
75
|
+
this.edges.push(rev)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
public function has_edge(from: ptr_uint, to: ptr_uint) -> bool:
|
|
79
|
+
let edge_span = this.edges.as_span()
|
|
80
|
+
var i: ptr_uint = 0
|
|
81
|
+
while i < edge_span.len:
|
|
82
|
+
let e = edge_span[i]
|
|
83
|
+
if e.from == from and e.to == to:
|
|
84
|
+
return true
|
|
85
|
+
i += 1
|
|
86
|
+
return false
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
public editable function remove_edge(from: ptr_uint, to: ptr_uint) -> bool:
|
|
90
|
+
let count = this.edges.len()
|
|
91
|
+
var i: ptr_uint = 0
|
|
92
|
+
while i < count:
|
|
93
|
+
let e_ptr = this.edges.get(i) else:
|
|
94
|
+
break
|
|
95
|
+
unsafe:
|
|
96
|
+
if read(e_ptr).from == from and read(e_ptr).to == to:
|
|
97
|
+
this.edges.swap_remove(i)
|
|
98
|
+
return true
|
|
99
|
+
i += 1
|
|
100
|
+
return false
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
public function neighbors(index: ptr_uint) -> vec.Vec[ptr_uint]:
|
|
104
|
+
var result = vec.Vec[ptr_uint].create()
|
|
105
|
+
let edge_span = this.edges.as_span()
|
|
106
|
+
var i: ptr_uint = 0
|
|
107
|
+
while i < edge_span.len:
|
|
108
|
+
let e = edge_span[i]
|
|
109
|
+
if e.from == index:
|
|
110
|
+
result.push(e.to)
|
|
111
|
+
i += 1
|
|
112
|
+
return result
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
public function bfs(start: ptr_uint) -> vec.Vec[ptr_uint]:
|
|
116
|
+
var order = vec.Vec[ptr_uint].create()
|
|
117
|
+
let n = this.node_count()
|
|
118
|
+
if n == 0 or start >= n:
|
|
119
|
+
return order
|
|
120
|
+
|
|
121
|
+
var visited = heap.must_alloc_zeroed[ubyte](n)
|
|
122
|
+
var queue = deque.Deque[ptr_uint].create()
|
|
123
|
+
|
|
124
|
+
queue.push_back(start)
|
|
125
|
+
unsafe:
|
|
126
|
+
visited[start] = 1
|
|
127
|
+
|
|
128
|
+
let edge_span = this.edges.as_span()
|
|
129
|
+
while not queue.is_empty():
|
|
130
|
+
let current = queue.pop_front() else:
|
|
131
|
+
break
|
|
132
|
+
order.push(current)
|
|
133
|
+
|
|
134
|
+
var i: ptr_uint = 0
|
|
135
|
+
while i < edge_span.len:
|
|
136
|
+
let e = edge_span[i]
|
|
137
|
+
if e.from == current:
|
|
138
|
+
unsafe:
|
|
139
|
+
if visited[e.to] == 0:
|
|
140
|
+
visited[e.to] = 1
|
|
141
|
+
queue.push_back(e.to)
|
|
142
|
+
i += 1
|
|
143
|
+
|
|
144
|
+
heap.release(visited)
|
|
145
|
+
queue.release()
|
|
146
|
+
return order
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
public function dfs(start: ptr_uint) -> vec.Vec[ptr_uint]:
|
|
150
|
+
var order = vec.Vec[ptr_uint].create()
|
|
151
|
+
let n = this.node_count()
|
|
152
|
+
if n == 0 or start >= n:
|
|
153
|
+
return order
|
|
154
|
+
|
|
155
|
+
var visited = heap.must_alloc_zeroed[ubyte](n)
|
|
156
|
+
|
|
157
|
+
var stack = deque.Deque[ptr_uint].create()
|
|
158
|
+
stack.push_back(start)
|
|
159
|
+
|
|
160
|
+
let edge_span = this.edges.as_span()
|
|
161
|
+
while not stack.is_empty():
|
|
162
|
+
let current = stack.pop_back() else:
|
|
163
|
+
break
|
|
164
|
+
unsafe:
|
|
165
|
+
if visited[current] != 0:
|
|
166
|
+
continue
|
|
167
|
+
visited[current] = 1
|
|
168
|
+
order.push(current)
|
|
169
|
+
|
|
170
|
+
var i: ptr_uint = 0
|
|
171
|
+
while i < edge_span.len:
|
|
172
|
+
let e = edge_span[i]
|
|
173
|
+
if e.from == current:
|
|
174
|
+
unsafe:
|
|
175
|
+
if visited[e.to] == 0:
|
|
176
|
+
stack.push_back(e.to)
|
|
177
|
+
i += 1
|
|
178
|
+
|
|
179
|
+
heap.release(visited)
|
|
180
|
+
stack.release()
|
|
181
|
+
return order
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
public function toposort() -> vec.Vec[ptr_uint]:
|
|
185
|
+
var order = vec.Vec[ptr_uint].create()
|
|
186
|
+
let n = this.node_count()
|
|
187
|
+
if n == 0:
|
|
188
|
+
return order
|
|
189
|
+
|
|
190
|
+
var in_degree = heap.must_alloc_zeroed[ptr_uint](n)
|
|
191
|
+
|
|
192
|
+
let edge_span = this.edges.as_span()
|
|
193
|
+
var i: ptr_uint = 0
|
|
194
|
+
while i < edge_span.len:
|
|
195
|
+
let e = edge_span[i]
|
|
196
|
+
unsafe:
|
|
197
|
+
in_degree[e.to] += 1
|
|
198
|
+
i += 1
|
|
199
|
+
|
|
200
|
+
var queue = deque.Deque[ptr_uint].create()
|
|
201
|
+
i = 0
|
|
202
|
+
while i < n:
|
|
203
|
+
unsafe:
|
|
204
|
+
if in_degree[i] == 0:
|
|
205
|
+
queue.push_back(i)
|
|
206
|
+
i += 1
|
|
207
|
+
|
|
208
|
+
while not queue.is_empty():
|
|
209
|
+
let current = queue.pop_front() else:
|
|
210
|
+
break
|
|
211
|
+
order.push(current)
|
|
212
|
+
|
|
213
|
+
var j: ptr_uint = 0
|
|
214
|
+
while j < edge_span.len:
|
|
215
|
+
let e = edge_span[j]
|
|
216
|
+
if e.from == current:
|
|
217
|
+
unsafe:
|
|
218
|
+
in_degree[e.to] -= 1
|
|
219
|
+
if in_degree[e.to] == 0:
|
|
220
|
+
queue.push_back(e.to)
|
|
221
|
+
j += 1
|
|
222
|
+
|
|
223
|
+
heap.release(in_degree)
|
|
224
|
+
queue.release()
|
|
225
|
+
return order
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
public function compile() -> DenseGraph[T]:
|
|
229
|
+
let n = this.node_count()
|
|
230
|
+
let m = this.edge_count()
|
|
231
|
+
|
|
232
|
+
var offsets = vec.Vec[ptr_uint].with_capacity(n + 1)
|
|
233
|
+
var targets = vec.Vec[ptr_uint].with_capacity(m)
|
|
234
|
+
var weights = vec.Vec[float].with_capacity(m)
|
|
235
|
+
|
|
236
|
+
var counts = heap.must_alloc[ptr_uint](n)
|
|
237
|
+
var pos = heap.must_alloc[ptr_uint](n)
|
|
238
|
+
var i: ptr_uint = 0
|
|
239
|
+
while i < n:
|
|
240
|
+
unsafe:
|
|
241
|
+
counts[i] = 0
|
|
242
|
+
i += 1
|
|
243
|
+
|
|
244
|
+
let edge_span = this.edges.as_span()
|
|
245
|
+
i = 0
|
|
246
|
+
while i < edge_span.len:
|
|
247
|
+
let e = edge_span[i]
|
|
248
|
+
unsafe:
|
|
249
|
+
counts[e.from] += 1
|
|
250
|
+
i += 1
|
|
251
|
+
|
|
252
|
+
offsets.push(0)
|
|
253
|
+
i = 0
|
|
254
|
+
while i < n:
|
|
255
|
+
unsafe:
|
|
256
|
+
let total = offsets.get(offsets.len() - 1) else:
|
|
257
|
+
break
|
|
258
|
+
let accum = read(total) + counts[i]
|
|
259
|
+
pos[i] = read(total)
|
|
260
|
+
offsets.push(accum)
|
|
261
|
+
i += 1
|
|
262
|
+
|
|
263
|
+
i = 0
|
|
264
|
+
while i < m:
|
|
265
|
+
targets.push(0)
|
|
266
|
+
weights.push(0.0)
|
|
267
|
+
i += 1
|
|
268
|
+
|
|
269
|
+
i = 0
|
|
270
|
+
while i < edge_span.len:
|
|
271
|
+
let e = edge_span[i]
|
|
272
|
+
unsafe:
|
|
273
|
+
let at = pos[e.from]
|
|
274
|
+
let t_ptr = targets.get(at) else:
|
|
275
|
+
break
|
|
276
|
+
let w_ptr = weights.get(at) else:
|
|
277
|
+
break
|
|
278
|
+
read(t_ptr) = e.to
|
|
279
|
+
read(w_ptr) = e.weight
|
|
280
|
+
pos[e.from] += 1
|
|
281
|
+
i += 1
|
|
282
|
+
|
|
283
|
+
heap.release(counts)
|
|
284
|
+
heap.release(pos)
|
|
285
|
+
|
|
286
|
+
# The dense graph owns an independent copy of the node values: Vec
|
|
287
|
+
# copies are shallow (they share the data pointer), so handing
|
|
288
|
+
# `this.nodes` to the DenseGraph directly would double-free when both
|
|
289
|
+
# graphs are released.
|
|
290
|
+
var node_copy = vec.Vec[T].with_capacity(n)
|
|
291
|
+
var old_span = this.nodes.as_span()
|
|
292
|
+
var ci: ptr_uint = 0
|
|
293
|
+
while ci < n:
|
|
294
|
+
unsafe:
|
|
295
|
+
node_copy.push(read(old_span.data + ci))
|
|
296
|
+
ci += 1
|
|
297
|
+
|
|
298
|
+
return DenseGraph[T](
|
|
299
|
+
nodes = node_copy,
|
|
300
|
+
offsets = offsets,
|
|
301
|
+
targets = targets,
|
|
302
|
+
weights = weights,
|
|
303
|
+
is_directed = this.is_directed
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
public editable function clear():
|
|
308
|
+
this.nodes.clear()
|
|
309
|
+
this.edges.clear()
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
public editable function release():
|
|
313
|
+
this.nodes.release()
|
|
314
|
+
this.edges.release()
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
extending DenseGraph[T]:
|
|
318
|
+
public function node_count() -> ptr_uint:
|
|
319
|
+
return this.nodes.len()
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
public function edge_count() -> ptr_uint:
|
|
323
|
+
return this.targets.len()
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
public function neighbor_count(node: ptr_uint) -> ptr_uint:
|
|
327
|
+
let n = this.node_count()
|
|
328
|
+
if node >= n:
|
|
329
|
+
return 0
|
|
330
|
+
let start = this.offsets.get(node) else:
|
|
331
|
+
return 0
|
|
332
|
+
let end = this.offsets.get(node + 1) else:
|
|
333
|
+
return 0
|
|
334
|
+
return unsafe: read(end) - read(start)
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
public function neighbor_target(node: ptr_uint, index: ptr_uint) -> ptr_uint:
|
|
338
|
+
let start = this.offsets.get(node) else:
|
|
339
|
+
fatal(c"dense_graph.neighbor_target: invalid node")
|
|
340
|
+
let target = this.targets.get(unsafe: read(start) + index) else:
|
|
341
|
+
fatal(c"dense_graph.neighbor_target: invalid neighbor index")
|
|
342
|
+
return unsafe: read(target)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
public function neighbor_weight(node: ptr_uint, index: ptr_uint) -> float:
|
|
346
|
+
let start = this.offsets.get(node) else:
|
|
347
|
+
fatal(c"dense_graph.neighbor_weight: invalid node")
|
|
348
|
+
let weight = this.weights.get(unsafe: read(start) + index) else:
|
|
349
|
+
fatal(c"dense_graph.neighbor_weight: invalid neighbor index")
|
|
350
|
+
return unsafe: read(weight)
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
public function has_edge(from: ptr_uint, to: ptr_uint) -> bool:
|
|
354
|
+
let start = this.offsets.get(from) else:
|
|
355
|
+
return false
|
|
356
|
+
let end = this.offsets.get(from + 1) else:
|
|
357
|
+
return false
|
|
358
|
+
let begin = unsafe: read(start)
|
|
359
|
+
let finish = unsafe: read(end)
|
|
360
|
+
var i = begin
|
|
361
|
+
while i < finish:
|
|
362
|
+
let t_ptr = this.targets.get(i) else:
|
|
363
|
+
break
|
|
364
|
+
unsafe:
|
|
365
|
+
if read(t_ptr) == to:
|
|
366
|
+
return true
|
|
367
|
+
i += 1
|
|
368
|
+
return false
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
public function bfs(start: ptr_uint) -> vec.Vec[ptr_uint]:
|
|
372
|
+
var order = vec.Vec[ptr_uint].create()
|
|
373
|
+
let n = this.node_count()
|
|
374
|
+
if n == 0 or start >= n:
|
|
375
|
+
return order
|
|
376
|
+
|
|
377
|
+
var visited = heap.must_alloc_zeroed[ubyte](n)
|
|
378
|
+
var queue = deque.Deque[ptr_uint].create()
|
|
379
|
+
|
|
380
|
+
queue.push_back(start)
|
|
381
|
+
unsafe:
|
|
382
|
+
visited[start] = 1
|
|
383
|
+
|
|
384
|
+
while not queue.is_empty():
|
|
385
|
+
let current = queue.pop_front() else:
|
|
386
|
+
break
|
|
387
|
+
order.push(current)
|
|
388
|
+
|
|
389
|
+
let cur_start_ptr = this.offsets.get(current) else:
|
|
390
|
+
break
|
|
391
|
+
let cur_end_ptr = this.offsets.get(current + 1) else:
|
|
392
|
+
break
|
|
393
|
+
let cur_start = unsafe: read(cur_start_ptr)
|
|
394
|
+
let cur_end = unsafe: read(cur_end_ptr)
|
|
395
|
+
var i = cur_start
|
|
396
|
+
while i < cur_end:
|
|
397
|
+
let t_ptr = this.targets.get(i) else:
|
|
398
|
+
break
|
|
399
|
+
let next = unsafe: read(t_ptr)
|
|
400
|
+
unsafe:
|
|
401
|
+
if visited[next] == 0:
|
|
402
|
+
visited[next] = 1
|
|
403
|
+
queue.push_back(next)
|
|
404
|
+
i += 1
|
|
405
|
+
|
|
406
|
+
heap.release(visited)
|
|
407
|
+
queue.release()
|
|
408
|
+
return order
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
public function dfs(start: ptr_uint) -> vec.Vec[ptr_uint]:
|
|
412
|
+
var order = vec.Vec[ptr_uint].create()
|
|
413
|
+
let n = this.node_count()
|
|
414
|
+
if n == 0 or start >= n:
|
|
415
|
+
return order
|
|
416
|
+
|
|
417
|
+
var visited = heap.must_alloc_zeroed[ubyte](n)
|
|
418
|
+
var stack = deque.Deque[ptr_uint].create()
|
|
419
|
+
stack.push_back(start)
|
|
420
|
+
|
|
421
|
+
while not stack.is_empty():
|
|
422
|
+
let current = stack.pop_back() else:
|
|
423
|
+
break
|
|
424
|
+
unsafe:
|
|
425
|
+
if visited[current] != 0:
|
|
426
|
+
continue
|
|
427
|
+
visited[current] = 1
|
|
428
|
+
order.push(current)
|
|
429
|
+
|
|
430
|
+
let cur_start_ptr = this.offsets.get(current) else:
|
|
431
|
+
break
|
|
432
|
+
let cur_end_ptr = this.offsets.get(current + 1) else:
|
|
433
|
+
break
|
|
434
|
+
let cur_start = unsafe: read(cur_start_ptr)
|
|
435
|
+
let cur_end = unsafe: read(cur_end_ptr)
|
|
436
|
+
var i = cur_start
|
|
437
|
+
while i < cur_end:
|
|
438
|
+
let t_ptr = this.targets.get(i) else:
|
|
439
|
+
break
|
|
440
|
+
let next = unsafe: read(t_ptr)
|
|
441
|
+
unsafe:
|
|
442
|
+
if visited[next] == 0:
|
|
443
|
+
stack.push_back(next)
|
|
444
|
+
i += 1
|
|
445
|
+
|
|
446
|
+
heap.release(visited)
|
|
447
|
+
stack.release()
|
|
448
|
+
return order
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
public function toposort() -> vec.Vec[ptr_uint]:
|
|
452
|
+
var order = vec.Vec[ptr_uint].create()
|
|
453
|
+
let n = this.node_count()
|
|
454
|
+
if n == 0:
|
|
455
|
+
return order
|
|
456
|
+
|
|
457
|
+
var in_degree = heap.must_alloc[ptr_uint](n)
|
|
458
|
+
|
|
459
|
+
var i: ptr_uint = 0
|
|
460
|
+
while i < n:
|
|
461
|
+
unsafe:
|
|
462
|
+
in_degree[i] = 0
|
|
463
|
+
i += 1
|
|
464
|
+
|
|
465
|
+
i = 0
|
|
466
|
+
while i < n:
|
|
467
|
+
let start_ptr = this.offsets.get(i) else:
|
|
468
|
+
break
|
|
469
|
+
let end_ptr = this.offsets.get(i + 1) else:
|
|
470
|
+
break
|
|
471
|
+
let start = unsafe: read(start_ptr)
|
|
472
|
+
let end = unsafe: read(end_ptr)
|
|
473
|
+
var j = start
|
|
474
|
+
while j < end:
|
|
475
|
+
let t_ptr = this.targets.get(j) else:
|
|
476
|
+
break
|
|
477
|
+
unsafe:
|
|
478
|
+
in_degree[read(t_ptr)] += 1
|
|
479
|
+
j += 1
|
|
480
|
+
i += 1
|
|
481
|
+
|
|
482
|
+
var queue = deque.Deque[ptr_uint].create()
|
|
483
|
+
i = 0
|
|
484
|
+
while i < n:
|
|
485
|
+
unsafe:
|
|
486
|
+
if in_degree[i] == 0:
|
|
487
|
+
queue.push_back(i)
|
|
488
|
+
i += 1
|
|
489
|
+
|
|
490
|
+
while not queue.is_empty():
|
|
491
|
+
let current = queue.pop_front() else:
|
|
492
|
+
break
|
|
493
|
+
order.push(current)
|
|
494
|
+
|
|
495
|
+
let cur_start_ptr = this.offsets.get(current) else:
|
|
496
|
+
break
|
|
497
|
+
let cur_end_ptr = this.offsets.get(current + 1) else:
|
|
498
|
+
break
|
|
499
|
+
let cur_start = unsafe: read(cur_start_ptr)
|
|
500
|
+
let cur_end = unsafe: read(cur_end_ptr)
|
|
501
|
+
var k = cur_start
|
|
502
|
+
while k < cur_end:
|
|
503
|
+
let t_ptr = this.targets.get(k) else:
|
|
504
|
+
break
|
|
505
|
+
let next = unsafe: read(t_ptr)
|
|
506
|
+
unsafe:
|
|
507
|
+
in_degree[next] -= 1
|
|
508
|
+
if in_degree[next] == 0:
|
|
509
|
+
queue.push_back(next)
|
|
510
|
+
k += 1
|
|
511
|
+
|
|
512
|
+
heap.release(in_degree)
|
|
513
|
+
queue.release()
|
|
514
|
+
return order
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
public editable function release():
|
|
518
|
+
this.nodes.release()
|
|
519
|
+
this.offsets.release()
|
|
520
|
+
this.targets.release()
|
|
521
|
+
this.weights.release()
|
data/std/gzip.mt
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import std.bytes as bytes
|
|
2
|
+
import std.c.zlib as c
|
|
3
|
+
import std.string as string
|
|
4
|
+
|
|
5
|
+
public const DEFAULT_COMPRESSION: int = c.MT_ZLIB_DEFAULT_COMPRESSION
|
|
6
|
+
public const BEST_SPEED: int = c.MT_ZLIB_BEST_SPEED
|
|
7
|
+
public const BEST_COMPRESSION: int = c.MT_ZLIB_BEST_COMPRESSION
|
|
8
|
+
|
|
9
|
+
public struct Error:
|
|
10
|
+
code: int
|
|
11
|
+
message: string.String
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
function take_owned_string(data: ptr[char]?, len: ptr_uint) -> string.String:
|
|
15
|
+
if data == null:
|
|
16
|
+
if len != 0:
|
|
17
|
+
fatal(c"gzip.take_owned_string missing storage")
|
|
18
|
+
|
|
19
|
+
return string.String.create()
|
|
20
|
+
|
|
21
|
+
return unsafe: string.String(data = ptr[ubyte]<-data, len = len, capacity = len, owns_storage = true)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
function take_owned_bytes(data: ptr[ubyte]?, len: ptr_uint) -> bytes.Bytes:
|
|
25
|
+
if data == null:
|
|
26
|
+
if len != 0:
|
|
27
|
+
fatal(c"gzip.take_owned_bytes missing storage")
|
|
28
|
+
|
|
29
|
+
return bytes.Bytes.empty()
|
|
30
|
+
|
|
31
|
+
return unsafe: bytes.Bytes(data = own[ubyte]<-data, len = len)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
function take_error(raw: c.mt_zlib_error, fallback: str) -> Error:
|
|
35
|
+
if raw.message_data == null and raw.message_len == 0:
|
|
36
|
+
return Error(code = raw.code, message = string.String.from_str(fallback))
|
|
37
|
+
|
|
38
|
+
return Error(code = raw.code, message = take_owned_string(raw.message_data, raw.message_len))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
function static_error(message: str) -> Error:
|
|
42
|
+
return Error(code = -1, message = string.String.from_str(message))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
extending Error:
|
|
46
|
+
public editable function release() -> void:
|
|
47
|
+
this.message.release()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
public function compress_bytes(data: span[ubyte]) -> Result[bytes.Bytes, Error]:
|
|
51
|
+
return compress_bytes_with_level(data, DEFAULT_COMPRESSION)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
public function compress_bytes_with_level(data: span[ubyte], level: int) -> Result[bytes.Bytes, Error]:
|
|
55
|
+
if level < DEFAULT_COMPRESSION or level > BEST_COMPRESSION:
|
|
56
|
+
return Result[
|
|
57
|
+
bytes.Bytes,
|
|
58
|
+
Error
|
|
59
|
+
].failure(error= static_error("gzip compression level must be between -1 and 9"))
|
|
60
|
+
|
|
61
|
+
var raw_bytes = zero[c.mt_zlib_bytes]
|
|
62
|
+
var raw_error = zero[c.mt_zlib_error]
|
|
63
|
+
let status_code = c.mt_gzip_compress(data.data, data.len, level, raw_bytes, raw_error)
|
|
64
|
+
if status_code != 0:
|
|
65
|
+
return Result[bytes.Bytes, Error].failure(error= take_error(raw_error, "gzip compress failed"))
|
|
66
|
+
|
|
67
|
+
return Result[bytes.Bytes, Error].success(value= take_owned_bytes(raw_bytes.data, raw_bytes.len))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
public function decompress_bytes(data: span[ubyte]) -> Result[bytes.Bytes, Error]:
|
|
71
|
+
var raw_bytes = zero[c.mt_zlib_bytes]
|
|
72
|
+
var raw_error = zero[c.mt_zlib_error]
|
|
73
|
+
let status_code = c.mt_gzip_decompress(data.data, data.len, raw_bytes, raw_error)
|
|
74
|
+
if status_code != 0:
|
|
75
|
+
return Result[bytes.Bytes, Error].failure(error= take_error(raw_error, "gzip decompress failed"))
|
|
76
|
+
|
|
77
|
+
return Result[bytes.Bytes, Error].success(value= take_owned_bytes(raw_bytes.data, raw_bytes.len))
|