compiler/ lib/ examples/ std/ arch/ rv64/ tests/ abi.sizes.rad 3.4 KiB aggregate.return.rad 4.0 KiB arith.assignment.rad 580 B arith.basic.rad 176 B arith.modulo.rad 96 B arith.subword.rad 3.8 KiB arith.sum.rad 177 B arith.w64.rad 4.1 KiB array.assign.rad 221 B array.bounds.check.rad 321 B array.index.assign.rad 367 B array.index.rad 249 B array.length.rad 262 B array.math.rad 1.2 KiB array.nested.assign.rad 319 B array.nested.rad 325 B array.record.elements.rad 1.7 KiB array.repeat.edge.rad 548 B array.repeat.rad 828 B array.return.rad 330 B array.slice.empty.rad 108 B array.slice.gen.end.rad 126 B array.slice.gen.index.rad 139 B array.slice.gen.open.rad 125 B array.slice.gen.start.end.rad 127 B array.slice.gen.start.rad 126 B array.slice.rad 759 B as.precedence.rad 212 B assert.basic.rad 387 B assert.fail.rad 138 B assert.false.rad 140 B assert.true.rad 100 B assign.mutable.rad 6.1 KiB assign.rad 129 B assign.shadow.mutable.rad 461 B binop.bitwise.rad 1.2 KiB binop.cmp.rad 426 B bool.comparison.array.rad 688 B bool.comparison.nested.gen.rad 1.0 KiB bool.comparison.opt.rad 905 B bool.comparison.record.gen.rad 1.0 KiB bool.comparison.record.rad 1.1 KiB bool.comparison.slice.gen.rad 157 B bool.comparison.slice.rad 4.1 KiB bool.comparison.slice.record.gen.rad 2.0 KiB bool.comparison.slice.union.gen.rad 2.5 KiB bool.comparison.union.ctor.rad 690 B bool.comparison.union.gen.rad 1.2 KiB bool.comparison.union.record.gen.rad 1.5 KiB bool.comparison.union.simple.gen.rad 281 B bool.operators.complex.rad 384 B bool.operators.rad 831 B bool.short.circuit.rad 2.3 KiB bool.simple.rad 194 B bool.values.rad 772 B builtin.size.align.rad 1.3 KiB builtin.sliceof.mut.rad 606 B builtin.sliceof.rad 505 B call.arg.clobber.rad 717 B call.basic.rad 241 B call.clobber.rad 462 B cast.same.size.rad 1.0 KiB casting.numbers.rad 1.5 KiB char.literal.rad 165 B compound.assign.field.rad 285 B compound.assign.rad 1.1 KiB cond.assign.rad 723 B cond.expr.aggregate.rad 1.1 KiB cond.expr.rad 1.8 KiB cond.for.else.break.rad 326 B cond.for.indexed.rad 238 B cond.for.rad 165 B cond.for.range.indexed.rad 526 B cond.for.range.rad 171 B cond.for.unsigned.range.rad 644 B cond.forever.break.continue.rad 182 B cond.forever.break.rad 232 B cond.fused.rad 926 B cond.if.case.rad 2.2 KiB cond.if.else.min.rad 143 B cond.if.else.rad 225 B cond.if.elseif.rad 420 B cond.if.noelse.rad 120 B cond.if.rad 865 B cond.match.fallthrough.rad 369 B cond.match.guard.rad 1.4 KiB cond.match.guard.regalloc.rad 1.3 KiB cond.while.else.break.rad 282 B cond.while.rad 119 B const.array.copy.mutate.rad 386 B const.array.rad 195 B const.basic.rad 325 B const.char.rad 159 B const.fn.array.rad 664 B const.record.array.rad 1.2 KiB const.record.array.simple.rad 523 B const.record.ctor.rad 170 B const.record.fn.rad 353 B const.record.rad 182 B const.slice.param.rad 333 B const.union.payload.ctor.rad 349 B const.union.record.literal.rad 359 B data.array.rad 767 B data.bool.rad 216 B data.i16.rad 261 B data.i32.rad 281 B data.i8.rad 248 B data.record.rad 561 B data.simple.rad 436 B data.u16.rad 220 B data.u32.rad 240 B data.u8.rad 208 B data.union.rad 886 B debug.tag.rad 557 B edge.cases.2.rad 337 B edge.cases.3.rad 594 B edge.cases.4.rad 1.2 KiB edge.cases.5.rad 1.0 KiB edge.cases.6.rad 2.6 KiB edge.cases.7.addr.bug.rad 224 B edge.cases.8.bug.rad 508 B edge.cases.rad 223 B error.basic.rad 159 B error.catch.rad 1.6 KiB error.division.zero.rad 164 B error.modulo.zero.rad 162 B error.multi.basic.rad 672 B error.multi.catch.rad 772 B error.multi.catch.typed.binding.rad 791 B error.multi.catch.typed.catchall.rad 1.0 KiB error.multi.catch.typed.rad 1.1 KiB error.multi.propagate.multi.rad 953 B error.multi.propagate.rad 825 B error.multi.try.optional.rad 507 B error.slice.bounds.rad 219 B error.try.bang.success.rad 370 B error.try.catch.binding.rad 2.0 KiB error.try.optional.rad 1.8 KiB error.try.rad 4.0 KiB fn.block.scope.rad 508 B fn.callback.nested.rad 1.2 KiB fn.default.rad 131 B fn.local.rad 140 B fn.recursion.2.rad 239 B fn.void.rad 150 B for.else.continue.rad 1.1 KiB frame.large.rad 567 B if-let-mut.rad 1.1 KiB iflet.shadow.leak.rad 317 B integer.bitwise.basic.rad 693 B integer.overflow.rad 1.8 KiB large.blit.store.rad 2.1 KiB let.guard.rad 1.9 KiB literal.w64.rad 1.7 KiB loc.addr.offset.bug.rad 410 B loc.addr.opt.to.opt.rad 433 B loc.addr.optional.assign.rad 408 B loc.addr.record.assign.rad 443 B loop.complex.flow.rad 1007 B loop.sealblock.rad 911 B match.array.rad 3.4 KiB match.char.rad 1.6 KiB match.multi.seal.rad 987 B match.multi.survive.rad 1.6 KiB match.mutref.push.rad 1.0 KiB match.mutref.union.rad 662 B match.nested.call.rad 1.7 KiB match.nested.deep.rad 2.2 KiB match.nested.deref.rad 3.7 KiB match.nested.guard.rad 1.6 KiB match.nested.iflet.guard.rad 1.6 KiB match.nested.iflet.rad 1.4 KiB match.nested.letelse.rad 813 B match.nested.letelse.union.rad 1.3 KiB match.nested.literal.rad 3.1 KiB match.nested.multi.rad 2.4 KiB match.nested.pattern.rad 5.2 KiB match.nested.record.rad 2.0 KiB match.nested.union.rad 2.3 KiB match.nested.whilelet.rad 2.4 KiB match.string.rad 1.8 KiB match.value.copy.rad 2.0 KiB match.void.then.or.rad 1.6 KiB memzero.result.bug.rad 806 B memzero.union.bug.rad 576 B mutref.loop.bug.rad 1.8 KiB opt.assignment.bug.rad 1.3 KiB opt.bug.test.rad 1.4 KiB opt.if.let.complex.rad 6.2 KiB opt.if.let.guard.rad 809 B opt.if.let.rad 956 B opt.nil.check.rad 1.5 KiB opt.record.eq.rad 842 B opt.record.rad 655 B opt.return.array.rad 289 B opt.return.nested.rad 797 B opt.return.record.rad 344 B opt.slice.npo.rad 2.8 KiB opt.type.rad 200 B opt.while.let.complex.rad 404 B panic.rad 111 B placeholder.basic.rad 133 B placeholder.comprehensive.rad 562 B pointer.copy.edge.case.rad 1.3 KiB pointer.slice.index.rad 269 B pointer.slice.store.rad 881 B prog.ackermann.rad 5.0 KiB prog.bignum.rad 9.4 KiB prog.binsearch.rad 2.4 KiB prog.bubblesort.rad 2.0 KiB prog.cordic.rad 6.9 KiB prog.crc32.rad 2.7 KiB prog.dijkstra.rad 7.7 KiB prog.eval.rad 6.2 KiB prog.hanoi.rad 3.8 KiB prog.huffman.rad 9.3 KiB prog.hybridsort.rad 3.0 KiB prog.linkedlist.rad 5.8 KiB prog.lzw.rad 6.7 KiB prog.matmul.rad 2.9 KiB prog.mersenne.rad 5.2 KiB prog.nqueens.rad 3.4 KiB prog.rbtree.rad 8.2 KiB prog.regex.rad 10.2 KiB prog.sha256.rad 7.0 KiB prog.sieve.rad 2.8 KiB prog.symtab.rad 10.1 KiB prog.tokenizer.rad 13.8 KiB prog.vm.rad 17.4 KiB ptr.assign.rad 137 B ptr.deref.rad 622 B ptr.eq.rad 966 B ptr.mutate.rad 244 B ptr.opaque.rad 1.4 KiB record.access.rad 285 B record.alignment.rad 179 B record.array.elements.rad 1.7 KiB record.copy.rad 2.0 KiB record.field.assign.rad 184 B record.nested.calls.2.rad 612 B record.nested.calls.3.rad 734 B record.param.lit.rad 353 B record.ptr.access.rad 227 B record.ptr.mutate.rad 243 B record.shorthand.rad 1.5 KiB record.unlabeled.rad 407 B ref.if.bug.rad 519 B ref.immut.loop.bug.rad 670 B ref.mut.ptr.rad 261 B regalloc.callee.save.rad 1.5 KiB regalloc.spill.reuse.rad 473 B reserve.loop.rad 392 B result.void.success.rad 716 B slice.alloc.loop.rad 788 B slice.append.rad 3.3 KiB slice.cap.rad 941 B slice.delete.rad 971 B slice.of.rad 460 B slice.subslice.rad 1.4 KiB spill.blockarg.clobber.rad 3.5 KiB spill.loop.rad 1.6 KiB stack.local.corrupt.rad 320 B static.array.mutate.rad 387 B static.basic.rad 327 B static.fn.array.rad 628 B static.record.array.rad 503 B static.slice.index.assign.rad 408 B static.slice.offset.rad 668 B string.basic.rad 149 B string.escape.rad 349 B string.index.rad 116 B switch.blockargs.clobber.rad 1.3 KiB trait.aggregate.ret.rad 1.5 KiB trait.array.optional.rad 1.7 KiB trait.basic.rad 565 B trait.control.flow.rad 1.1 KiB trait.fn.param.rad 1.6 KiB trait.multiple.methods.rad 1.2 KiB trait.multiple.traits.rad 1.2 KiB trait.multiple.types.rad 1.3 KiB trait.supertrait.rad 2.5 KiB trait.throws.rad 1.0 KiB trait.writer.rad 2.6 KiB type.unify.rad 4.5 KiB undefined.rad 417 B union-tag.rad 911 B union.bitfield.rad 1.2 KiB union.discriminant.cast.rad 389 B union.edge.case.2.rad 679 B union.edge.case.3.rad 608 B union.mixed.assign.rad 977 B union.payload.mutref.rad 1.4 KiB union.payload.rad 580 B union.record.forward.rad 1.3 KiB union.void.match.rad 403 B union.void.rad 824 B unsigned.compare.rad 1.9 KiB var.align.rad 1013 B var.infer.rad 549 B decode.rad 14.6 KiB emit.rad 24.4 KiB encode.rad 19.9 KiB isel.rad 41.1 KiB printer.rad 13.0 KiB tests.rad 15.7 KiB rv64.rad 13.0 KiB collections/ lang/ sys/ arch.rad 65 B collections.rad 36 B fmt.rad 3.8 KiB intrinsics.rad 206 B io.rad 1.2 KiB lang.rad 222 B mem.rad 2.2 KiB sys.rad 167 B testing.rad 2.4 KiB tests.rad 11.6 KiB vec.rad 3.1 KiB std.rad 231 B scripts/ seed/ test/ vim/ .gitignore 353 B .gitsigners 112 B LICENSE 1.1 KiB Makefile 3.1 KiB README 2.5 KiB std.lib 987 B std.lib.test 252 B
lib/std/arch/rv64/tests/prog.dijkstra.rad 7.7 KiB raw
1
//! Dijkstra's shortest path algorithm.
2
//! Find shortest paths in a weighted directed graph using an adjacency matrix
3
//! and a min-heap priority queue. Reconstruct paths and verify distances.
4
5
6
const MAX_NODES: u32 = 16;
7
const INF: u32 = 0xFFFFFFFF;
8
9
record HeapEntry {
10
    dist: u32,
11
    node: u32,
12
}
13
14
record Graph {
15
    adj: *mut [[u32; 16]],
16
    dist: *mut [u32],
17
    prev: *mut [i32],
18
    visited: *mut [bool],
19
    numNodes: u32,
20
    heap: *mut [HeapEntry],
21
    heapSize: u32,
22
}
23
24
fn heapSwap(g: *mut Graph, i: u32, j: u32) {
25
    let tmp: HeapEntry = g.heap[i];
26
    g.heap[i] = g.heap[j];
27
    g.heap[j] = tmp;
28
}
29
30
fn siftUp(g: *mut Graph, pos: u32) {
31
    let mut i: u32 = pos;
32
    while i > 0 {
33
        let parent: u32 = (i - 1) / 2;
34
        if g.heap[i].dist < g.heap[parent].dist {
35
            heapSwap(g, i, parent);
36
            i = parent;
37
        } else {
38
            return;
39
        }
40
    }
41
}
42
43
fn siftDown(g: *mut Graph, pos: u32) {
44
    let mut i: u32 = pos;
45
    while true {
46
        let left: u32 = 2 * i + 1;
47
        let right: u32 = 2 * i + 2;
48
        let mut smallest: u32 = i;
49
50
        if left < g.heapSize and g.heap[left].dist < g.heap[smallest].dist {
51
            smallest = left;
52
        }
53
        if right < g.heapSize and g.heap[right].dist < g.heap[smallest].dist {
54
            smallest = right;
55
        }
56
        if smallest == i {
57
            return;
58
        }
59
        heapSwap(g, i, smallest);
60
        i = smallest;
61
    }
62
}
63
64
fn heapPush(g: *mut Graph, dist: u32, node: u32) {
65
    g.heap[g.heapSize] = HeapEntry { dist, node };
66
    g.heapSize += 1;
67
    siftUp(g, g.heapSize - 1);
68
}
69
70
/// Pop from the heap. Returns nil if the heap is empty.
71
fn heapPop(g: *mut Graph) -> ?HeapEntry {
72
    if g.heapSize == 0 {
73
        return nil;
74
    }
75
    let result: HeapEntry = g.heap[0];
76
    g.heapSize -= 1;
77
    g.heap[0] = g.heap[g.heapSize];
78
    if g.heapSize > 0 {
79
        siftDown(g, 0);
80
    }
81
    return result;
82
}
83
84
fn addEdge(g: *mut Graph, from: u32, to: u32, weight: u32) {
85
    g.adj[from][to] = weight;
86
}
87
88
fn addBidiEdge(g: *mut Graph, from: u32, to: u32, weight: u32) {
89
    g.adj[from][to] = weight;
90
    g.adj[to][from] = weight;
91
}
92
93
fn resetGraph(g: *mut Graph, n: u32) {
94
    g.numNodes = n;
95
    let mut i: u32 = 0;
96
    while i < MAX_NODES {
97
        let mut j: u32 = 0;
98
        while j < MAX_NODES {
99
            g.adj[i][j] = INF;
100
            j += 1;
101
        }
102
        g.dist[i] = INF;
103
        g.prev[i] = -1;
104
        g.visited[i] = false;
105
        i += 1;
106
    }
107
    g.heapSize = 0;
108
}
109
110
/// Get the predecessor as an optional; -1 means no predecessor.
111
fn getPrev(g: *Graph, node: u32) -> ?u32 {
112
    let p = g.prev[node];
113
    if p < 0 {
114
        return nil;
115
    }
116
    return p as u32;
117
}
118
119
fn dijkstra(g: *mut Graph, source: u32) {
120
    g.dist[source] = 0;
121
    heapPush(g, 0, source);
122
123
    while let entry = heapPop(g) {
124
        let u: u32 = entry.node;
125
126
        if g.visited[u] {
127
            continue;
128
        }
129
        g.visited[u] = true;
130
131
        let mut v: u32 = 0;
132
        while v < g.numNodes {
133
            if g.adj[u][v] != INF and not g.visited[v] {
134
                let newDist: u32 = g.dist[u] + g.adj[u][v];
135
                if newDist < g.dist[v] {
136
                    g.dist[v] = newDist;
137
                    g.prev[v] = u as i32;
138
                    heapPush(g, newDist, v);
139
                }
140
            }
141
            v += 1;
142
        }
143
    }
144
}
145
146
/// Reconstruct the shortest path from source to target.
147
fn reconstructPath(g: *Graph, target: u32, path: *mut [u32]) -> u32 {
148
    let mut len: u32 = 0;
149
150
    path[len] = target;
151
    len += 1;
152
153
    let mut cur: ?u32 = getPrev(g, target);
154
    while let node = cur {
155
        path[len] = node;
156
        len += 1;
157
        cur = getPrev(g, node);
158
    }
159
160
    // Reverse the path.
161
    let mut a: u32 = 0;
162
    let mut b: u32 = len - 1;
163
    while a < b {
164
        let tmp: u32 = path[a];
165
        path[a] = path[b];
166
        path[b] = tmp;
167
        a += 1;
168
        b -= 1;
169
    }
170
    return len;
171
}
172
173
fn testLinear(g: *mut Graph) -> i32 {
174
    resetGraph(g, 5);
175
    addEdge(g, 0, 1, 10);
176
    addEdge(g, 1, 2, 10);
177
    addEdge(g, 2, 3, 10);
178
    addEdge(g, 3, 4, 10);
179
180
    dijkstra(g, 0);
181
182
183
    let expected: [u32; 5] = [0, 10, 20, 30, 40];
184
    for exp, i in expected {
185
        if g.dist[i] != exp {
186
            return i as i32 + 1;
187
        }
188
    }
189
190
    let mut path: [u32; 16] = [0; 16];
191
    let len: u32 = reconstructPath(g, 4, &mut path[..]);
192
    assert len == 5;
193
    assert path[0] == 0;
194
    assert path[4] == 4;
195
196
    return 0;
197
}
198
199
fn testShortcut(g: *mut Graph) -> i32 {
200
    resetGraph(g, 4);
201
    addEdge(g, 0, 1, 10);
202
    addEdge(g, 1, 2, 10);
203
    addEdge(g, 0, 3, 5);
204
    addEdge(g, 3, 2, 3);
205
206
    dijkstra(g, 0);
207
208
    assert g.dist[2] == 8;
209
210
    let prev2 = getPrev(g, 2) else {
211
        return 2;
212
    };
213
    assert prev2 == 3;
214
215
    return 0;
216
}
217
218
fn testBidirectional(g: *mut Graph) -> i32 {
219
    resetGraph(g, 5);
220
    addBidiEdge(g, 0, 1, 1);
221
    addBidiEdge(g, 1, 2, 2);
222
    addBidiEdge(g, 2, 3, 3);
223
    addBidiEdge(g, 3, 0, 4);
224
    addBidiEdge(g, 0, 4, 7);
225
    addBidiEdge(g, 1, 4, 5);
226
    addBidiEdge(g, 2, 4, 1);
227
228
    dijkstra(g, 0);
229
230
    let expected: [u32; 5] = [0, 1, 3, 4, 4];
231
    for exp, i in expected {
232
        if g.dist[i] != exp {
233
            return i as i32 + 1;
234
        }
235
    }
236
237
    return 0;
238
}
239
240
fn testComplete(g: *mut Graph) -> i32 {
241
    resetGraph(g, 8);
242
243
    let mut i: u32 = 0;
244
    while i < 8 {
245
        let mut j: u32 = 0;
246
        while j < 8 {
247
            if i != j {
248
                let mut diff: u32 = j - i;
249
                if i > j {
250
                    diff = i - j;
251
                }
252
                addEdge(g, i, j, diff * 3 + 1);
253
            }
254
            j += 1;
255
        }
256
        i += 1;
257
    }
258
259
    dijkstra(g, 0);
260
261
    let mut k: u32 = 1;
262
    while k < 8 {
263
        let expected: u32 = k * 3 + 1;
264
        if g.dist[k] != expected {
265
            return k as i32;
266
        }
267
        k += 1;
268
    }
269
270
    return 0;
271
}
272
273
fn testDisconnected(g: *mut Graph) -> i32 {
274
    resetGraph(g, 6);
275
    addEdge(g, 0, 1, 5);
276
    addEdge(g, 1, 2, 3);
277
    addEdge(g, 3, 4, 2);
278
    addEdge(g, 4, 5, 1);
279
280
    dijkstra(g, 0);
281
282
    assert g.dist[0] == 0;
283
    assert g.dist[1] == 5;
284
    assert g.dist[2] == 8;
285
    // Unreachable nodes stay at INF.
286
    assert g.dist[3] == INF;
287
    assert g.dist[4] == INF;
288
    assert g.dist[5] == INF;
289
290
    // Predecessors of unreachable nodes should be nil.
291
    assert getPrev(g, 3) == nil;
292
293
    return 0;
294
}
295
296
fn testDiamond(g: *mut Graph) -> i32 {
297
    resetGraph(g, 5);
298
    addEdge(g, 0, 1, 5);
299
    addEdge(g, 0, 2, 5);
300
    addEdge(g, 1, 3, 5);
301
    addEdge(g, 2, 3, 5);
302
    addEdge(g, 3, 4, 2);
303
304
    dijkstra(g, 0);
305
306
    assert g.dist[3] == 10;
307
    assert g.dist[4] == 12;
308
    // Predecessor should be 1 or 2.
309
    let prev3 = getPrev(g, 3) else {
310
        return 3;
311
    };
312
    assert prev3 == 1 or prev3 == 2;
313
314
    return 0;
315
}
316
317
@default fn main() -> i32 {
318
    let mut adj: [[u32; 16]; 16] = [[0xFFFFFFFF; 16]; 16];
319
    let mut dist: [u32; 16] = [0xFFFFFFFF; 16];
320
    let mut prev: [i32; 16] = [-1; 16];
321
    let mut visited: [bool; 16] = [false; 16];
322
    let mut heap: [HeapEntry; 256] = [HeapEntry { dist: 0, node: 0 }; 256];
323
324
    let mut g: Graph = Graph {
325
        adj: &mut adj[..],
326
        dist: &mut dist[..],
327
        prev: &mut prev[..],
328
        visited: &mut visited[..],
329
        numNodes: 0,
330
        heap: &mut heap[..],
331
        heapSize: 0,
332
    };
333
334
    let r1: i32 = testLinear(&mut g);
335
    if r1 != 0 {
336
        return 10 + r1;
337
    }
338
339
    let r2: i32 = testShortcut(&mut g);
340
    if r2 != 0 {
341
        return 20 + r2;
342
    }
343
344
    let r3: i32 = testBidirectional(&mut g);
345
    if r3 != 0 {
346
        return 30 + r3;
347
    }
348
349
    let r4: i32 = testComplete(&mut g);
350
    if r4 != 0 {
351
        return 40 + r4;
352
    }
353
354
    let r5: i32 = testDisconnected(&mut g);
355
    if r5 != 0 {
356
        return 50 + r5;
357
    }
358
359
    let r6: i32 = testDiamond(&mut g);
360
    if r6 != 0 {
361
        return 60 + r6;
362
    }
363
364
    return 0;
365
}