@graphty/graph-format 0.0.0 → 0.2.0

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.
Files changed (224) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +216 -43
  3. package/dist/graph-format.d.ts +1 -0
  4. package/dist/graph-format.d.ts.map +1 -0
  5. package/dist/graph-format.js +15798 -0
  6. package/dist/graph-format.js.map +1 -0
  7. package/dist/src/builder/arena.d.ts +85 -0
  8. package/dist/src/builder/arena.d.ts.map +1 -0
  9. package/dist/src/builder/arena.js +154 -0
  10. package/dist/src/builder/arena.js.map +1 -0
  11. package/dist/src/builder/compact.d.ts +515 -0
  12. package/dist/src/builder/compact.d.ts.map +1 -0
  13. package/dist/src/builder/compact.js +1553 -0
  14. package/dist/src/builder/compact.js.map +1 -0
  15. package/dist/src/builder/counting-sort.d.ts +96 -0
  16. package/dist/src/builder/counting-sort.d.ts.map +1 -0
  17. package/dist/src/builder/counting-sort.js +430 -0
  18. package/dist/src/builder/counting-sort.js.map +1 -0
  19. package/dist/src/builder/freeze.d.ts +72 -0
  20. package/dist/src/builder/freeze.d.ts.map +1 -0
  21. package/dist/src/builder/freeze.js +548 -0
  22. package/dist/src/builder/freeze.js.map +1 -0
  23. package/dist/src/builder/graph-builder.d.ts +602 -0
  24. package/dist/src/builder/graph-builder.d.ts.map +1 -0
  25. package/dist/src/builder/graph-builder.js +1940 -0
  26. package/dist/src/builder/graph-builder.js.map +1 -0
  27. package/dist/src/builder/options.d.ts +16 -0
  28. package/dist/src/builder/options.d.ts.map +1 -0
  29. package/dist/src/builder/options.js +21 -0
  30. package/dist/src/builder/options.js.map +1 -0
  31. package/dist/src/columns/bitmap.d.ts +96 -0
  32. package/dist/src/columns/bitmap.d.ts.map +1 -0
  33. package/dist/src/columns/bitmap.js +184 -0
  34. package/dist/src/columns/bitmap.js.map +1 -0
  35. package/dist/src/columns/column.d.ts +220 -0
  36. package/dist/src/columns/column.d.ts.map +1 -0
  37. package/dist/src/columns/column.js +2109 -0
  38. package/dist/src/columns/column.js.map +1 -0
  39. package/dist/src/columns/dictionary.d.ts +60 -0
  40. package/dist/src/columns/dictionary.d.ts.map +1 -0
  41. package/dist/src/columns/dictionary.js +102 -0
  42. package/dist/src/columns/dictionary.js.map +1 -0
  43. package/dist/src/columns/growable.d.ts +198 -0
  44. package/dist/src/columns/growable.d.ts.map +1 -0
  45. package/dist/src/columns/growable.js +296 -0
  46. package/dist/src/columns/growable.js.map +1 -0
  47. package/dist/src/columns/infer.d.ts +121 -0
  48. package/dist/src/columns/infer.d.ts.map +1 -0
  49. package/dist/src/columns/infer.js +268 -0
  50. package/dist/src/columns/infer.js.map +1 -0
  51. package/dist/src/columns/remap.d.ts +143 -0
  52. package/dist/src/columns/remap.d.ts.map +1 -0
  53. package/dist/src/columns/remap.js +588 -0
  54. package/dist/src/columns/remap.js.map +1 -0
  55. package/dist/src/columns/table.d.ts +184 -0
  56. package/dist/src/columns/table.d.ts.map +1 -0
  57. package/dist/src/columns/table.js +485 -0
  58. package/dist/src/columns/table.js.map +1 -0
  59. package/dist/src/constants.d.ts +34 -0
  60. package/dist/src/constants.d.ts.map +1 -0
  61. package/dist/src/constants.js +79 -0
  62. package/dist/src/constants.js.map +1 -0
  63. package/dist/src/errors.d.ts +76 -0
  64. package/dist/src/errors.d.ts.map +1 -0
  65. package/dist/src/errors.js +32 -0
  66. package/dist/src/errors.js.map +1 -0
  67. package/dist/src/ids/edge-id-index.d.ts +77 -0
  68. package/dist/src/ids/edge-id-index.d.ts.map +1 -0
  69. package/dist/src/ids/edge-id-index.js +155 -0
  70. package/dist/src/ids/edge-id-index.js.map +1 -0
  71. package/dist/src/ids/node-id-map.d.ts +280 -0
  72. package/dist/src/ids/node-id-map.d.ts.map +1 -0
  73. package/dist/src/ids/node-id-map.js +1139 -0
  74. package/dist/src/ids/node-id-map.js.map +1 -0
  75. package/dist/src/ids/string-store.d.ts +219 -0
  76. package/dist/src/ids/string-store.d.ts.map +1 -0
  77. package/dist/src/ids/string-store.js +526 -0
  78. package/dist/src/ids/string-store.js.map +1 -0
  79. package/dist/src/index.d.ts +30 -0
  80. package/dist/src/index.d.ts.map +1 -0
  81. package/dist/src/index.js +29 -0
  82. package/dist/src/index.js.map +1 -0
  83. package/dist/src/populate/from-csr.d.ts +61 -0
  84. package/dist/src/populate/from-csr.d.ts.map +1 -0
  85. package/dist/src/populate/from-csr.js +706 -0
  86. package/dist/src/populate/from-csr.js.map +1 -0
  87. package/dist/src/populate/from-edge-arrays.d.ts +51 -0
  88. package/dist/src/populate/from-edge-arrays.d.ts.map +1 -0
  89. package/dist/src/populate/from-edge-arrays.js +217 -0
  90. package/dist/src/populate/from-edge-arrays.js.map +1 -0
  91. package/dist/src/populate/from-records.d.ts +51 -0
  92. package/dist/src/populate/from-records.d.ts.map +1 -0
  93. package/dist/src/populate/from-records.js +447 -0
  94. package/dist/src/populate/from-records.js.map +1 -0
  95. package/dist/src/snapshot/derived.d.ts +211 -0
  96. package/dist/src/snapshot/derived.d.ts.map +1 -0
  97. package/dist/src/snapshot/derived.js +1254 -0
  98. package/dist/src/snapshot/derived.js.map +1 -0
  99. package/dist/src/snapshot/graph-meta.d.ts +23 -0
  100. package/dist/src/snapshot/graph-meta.d.ts.map +1 -0
  101. package/dist/src/snapshot/graph-meta.js +159 -0
  102. package/dist/src/snapshot/graph-meta.js.map +1 -0
  103. package/dist/src/snapshot/graph-snapshot.d.ts +509 -0
  104. package/dist/src/snapshot/graph-snapshot.d.ts.map +1 -0
  105. package/dist/src/snapshot/graph-snapshot.js +1247 -0
  106. package/dist/src/snapshot/graph-snapshot.js.map +1 -0
  107. package/dist/src/snapshot/hash.d.ts +90 -0
  108. package/dist/src/snapshot/hash.d.ts.map +1 -0
  109. package/dist/src/snapshot/hash.js +228 -0
  110. package/dist/src/snapshot/hash.js.map +1 -0
  111. package/dist/src/snapshot/queries.d.ts +74 -0
  112. package/dist/src/snapshot/queries.d.ts.map +1 -0
  113. package/dist/src/snapshot/queries.js +131 -0
  114. package/dist/src/snapshot/queries.js.map +1 -0
  115. package/dist/src/snapshot/validate.d.ts +192 -0
  116. package/dist/src/snapshot/validate.d.ts.map +1 -0
  117. package/dist/src/snapshot/validate.js +990 -0
  118. package/dist/src/snapshot/validate.js.map +1 -0
  119. package/dist/src/snapshot/views.d.ts +274 -0
  120. package/dist/src/snapshot/views.d.ts.map +1 -0
  121. package/dist/src/snapshot/views.js +856 -0
  122. package/dist/src/snapshot/views.js.map +1 -0
  123. package/dist/src/types/builder.d.ts +456 -0
  124. package/dist/src/types/builder.d.ts.map +1 -0
  125. package/dist/src/types/builder.js +11 -0
  126. package/dist/src/types/builder.js.map +1 -0
  127. package/dist/src/types/columns.d.ts +615 -0
  128. package/dist/src/types/columns.d.ts.map +1 -0
  129. package/dist/src/types/columns.js +14 -0
  130. package/dist/src/types/columns.js.map +1 -0
  131. package/dist/src/types/index.d.ts +14 -0
  132. package/dist/src/types/index.d.ts.map +1 -0
  133. package/dist/src/types/index.js +11 -0
  134. package/dist/src/types/index.js.map +1 -0
  135. package/dist/src/types/internal.d.ts +172 -0
  136. package/dist/src/types/internal.d.ts.map +1 -0
  137. package/dist/src/types/internal.js +13 -0
  138. package/dist/src/types/internal.js.map +1 -0
  139. package/dist/src/types/snapshot.d.ts +801 -0
  140. package/dist/src/types/snapshot.d.ts.map +1 -0
  141. package/dist/src/types/snapshot.js +14 -0
  142. package/dist/src/types/snapshot.js.map +1 -0
  143. package/dist/src/types/wire.d.ts +196 -0
  144. package/dist/src/types/wire.d.ts.map +1 -0
  145. package/dist/src/types/wire.js +8 -0
  146. package/dist/src/types/wire.js.map +1 -0
  147. package/dist/src/util/mask.d.ts +55 -0
  148. package/dist/src/util/mask.d.ts.map +1 -0
  149. package/dist/src/util/mask.js +71 -0
  150. package/dist/src/util/mask.js.map +1 -0
  151. package/dist/src/util/options.d.ts +22 -0
  152. package/dist/src/util/options.d.ts.map +1 -0
  153. package/dist/src/util/options.js +49 -0
  154. package/dist/src/util/options.js.map +1 -0
  155. package/dist/src/util/shared-buffers.d.ts +42 -0
  156. package/dist/src/util/shared-buffers.d.ts.map +1 -0
  157. package/dist/src/util/shared-buffers.js +52 -0
  158. package/dist/src/util/shared-buffers.js.map +1 -0
  159. package/dist/src/util/typed-array.d.ts +205 -0
  160. package/dist/src/util/typed-array.d.ts.map +1 -0
  161. package/dist/src/util/typed-array.js +289 -0
  162. package/dist/src/util/typed-array.js.map +1 -0
  163. package/dist/src/wire/bytes.d.ts +69 -0
  164. package/dist/src/wire/bytes.d.ts.map +1 -0
  165. package/dist/src/wire/bytes.js +361 -0
  166. package/dist/src/wire/bytes.js.map +1 -0
  167. package/dist/src/wire/carried-views.d.ts +111 -0
  168. package/dist/src/wire/carried-views.d.ts.map +1 -0
  169. package/dist/src/wire/carried-views.js +286 -0
  170. package/dist/src/wire/carried-views.js.map +1 -0
  171. package/dist/src/wire/from-wire.d.ts +144 -0
  172. package/dist/src/wire/from-wire.d.ts.map +1 -0
  173. package/dist/src/wire/from-wire.js +1425 -0
  174. package/dist/src/wire/from-wire.js.map +1 -0
  175. package/dist/src/wire/to-wire.d.ts +171 -0
  176. package/dist/src/wire/to-wire.d.ts.map +1 -0
  177. package/dist/src/wire/to-wire.js +652 -0
  178. package/dist/src/wire/to-wire.js.map +1 -0
  179. package/dist/tsconfig.build.tsbuildinfo +1 -0
  180. package/package.json +72 -7
  181. package/src/builder/arena.ts +192 -0
  182. package/src/builder/compact.ts +1811 -0
  183. package/src/builder/counting-sort.ts +506 -0
  184. package/src/builder/freeze.ts +689 -0
  185. package/src/builder/graph-builder.ts +2264 -0
  186. package/src/builder/options.ts +29 -0
  187. package/src/columns/bitmap.ts +196 -0
  188. package/src/columns/column.ts +2574 -0
  189. package/src/columns/dictionary.ts +114 -0
  190. package/src/columns/growable.ts +350 -0
  191. package/src/columns/infer.ts +285 -0
  192. package/src/columns/remap.ts +663 -0
  193. package/src/columns/table.ts +568 -0
  194. package/src/constants.ts +89 -0
  195. package/src/errors.ts +115 -0
  196. package/src/ids/edge-id-index.ts +179 -0
  197. package/src/ids/node-id-map.ts +1340 -0
  198. package/src/ids/string-store.ts +589 -0
  199. package/src/index.ts +139 -0
  200. package/src/lib-resizable-array-buffer.d.ts +34 -0
  201. package/src/populate/from-csr.ts +802 -0
  202. package/src/populate/from-edge-arrays.ts +257 -0
  203. package/src/populate/from-records.ts +536 -0
  204. package/src/snapshot/derived.ts +1486 -0
  205. package/src/snapshot/graph-meta.ts +167 -0
  206. package/src/snapshot/graph-snapshot.ts +1503 -0
  207. package/src/snapshot/hash.ts +241 -0
  208. package/src/snapshot/queries.ts +136 -0
  209. package/src/snapshot/validate.ts +1108 -0
  210. package/src/snapshot/views.ts +943 -0
  211. package/src/types/builder.ts +480 -0
  212. package/src/types/columns.ts +727 -0
  213. package/src/types/index.ts +14 -0
  214. package/src/types/internal.ts +195 -0
  215. package/src/types/snapshot.ts +886 -0
  216. package/src/types/wire.ts +207 -0
  217. package/src/util/mask.ts +89 -0
  218. package/src/util/options.ts +57 -0
  219. package/src/util/shared-buffers.ts +56 -0
  220. package/src/util/typed-array.ts +371 -0
  221. package/src/wire/bytes.ts +440 -0
  222. package/src/wire/carried-views.ts +327 -0
  223. package/src/wire/from-wire.ts +1690 -0
  224. package/src/wire/to-wire.ts +755 -0
@@ -0,0 +1,327 @@
1
+ /**
2
+ * Content checks of the views a wire manifest carries (`includeViews`, design sections 9.1 and 9.5),
3
+ * run at the "structure" level before a carried view is installed on the receiver. Every view is a
4
+ * pure function of the core (design section 7.2), so each check is exact: the index views are
5
+ * compared with what the core says arc by arc in O(n + m) without allocating a second copy, and the
6
+ * four f64 views are compared with the snapshot's own computation. A view that disagrees is
7
+ * E_INVALID_SNAPSHOT with `details.invariant` "I2" (a corrupt index array) or "I17" (a corrupt
8
+ * value array) and `details.view` naming it. At "none" nothing is checked (the manifest is trusted,
9
+ * design section 9.5); at "full" carried views are never installed.
10
+ */
11
+
12
+ import { type GraphFormatError } from "../errors.js";
13
+ import { type GraphSnapshot } from "../snapshot/graph-snapshot.js";
14
+ import { invariantViolation } from "../snapshot/validate.js";
15
+ import { DEGREE_TIER_HIGH, DEGREE_TIER_MID, rowLengths } from "../snapshot/views.js";
16
+ import { type F32, type F64, type ReverseView, type U32 } from "../types/index.js";
17
+
18
+ /** The per-arc facts every index-view check reads, computed once per manifest. */
19
+ export class CoreFacts {
20
+ /** The row (source) of every arc. */
21
+ readonly arcRow: U32;
22
+ /** Loop arcs per node. */
23
+ readonly loops: U32;
24
+ /** In-arcs per node (directed only; the out-degree when undirected). */
25
+ readonly inDegree: U32;
26
+
27
+ /**
28
+ * Expand the core once.
29
+ * @param snapshot - the snapshot
30
+ */
31
+ constructor(snapshot: GraphSnapshot) {
32
+ const { nodeCount, arcCount, rowPtr, colIdx, directed } = snapshot;
33
+ const arcRow = new Uint32Array(arcCount);
34
+ const loops = new Uint32Array(nodeCount);
35
+ const inDegree = directed ? new Uint32Array(nodeCount) : rowLengths(rowPtr, nodeCount);
36
+ for (let u = 0; u < nodeCount; u++) {
37
+ const end = rowPtr[u + 1];
38
+ for (let a = rowPtr[u]; a < end; a++) {
39
+ arcRow[a] = u;
40
+ const v = colIdx[a];
41
+ if (v === u) {
42
+ loops[u]++;
43
+ }
44
+ if (directed) {
45
+ inDegree[v]++;
46
+ }
47
+ }
48
+ }
49
+ this.arcRow = arcRow;
50
+ this.loops = loops;
51
+ this.inDegree = inDegree;
52
+ }
53
+
54
+ /**
55
+ * The exclusive prefix sum of the in-degrees (the reverse rowPtr).
56
+ * @returns nodeCount + 1 offsets
57
+ */
58
+ inDegreePrefix(): U32 {
59
+ const n = this.inDegree.length;
60
+ const out = new Uint32Array(n + 1);
61
+ for (let u = 0; u < n; u++) {
62
+ out[u + 1] = out[u] + this.inDegree[u];
63
+ }
64
+ return out;
65
+ }
66
+ }
67
+
68
+ /**
69
+ * The error for a carried view that disagrees with the core.
70
+ * @param view - the view name
71
+ * @param member - the member array
72
+ * @param index - the offending index
73
+ * @param invariant - "I2" for an index array, "I17" for a value array
74
+ * @returns the error
75
+ */
76
+ function viewError(view: string, member: string, index: number, invariant: "I2" | "I17"): GraphFormatError {
77
+ return invariantViolation(invariant, `carried view ${view}.${member} disagrees with the core at ${index}`, {
78
+ view,
79
+ member,
80
+ index,
81
+ reason: "view",
82
+ });
83
+ }
84
+
85
+ /**
86
+ * Compare two arrays element by element (NaN equal to NaN).
87
+ * @param view - the view name
88
+ * @param member - the member name
89
+ * @param found - the carried array
90
+ * @param expected - the truth
91
+ * @param invariant - the invariant to report
92
+ */
93
+ function expectSame(
94
+ view: string,
95
+ member: string,
96
+ found: ArrayLike<number>,
97
+ expected: ArrayLike<number>,
98
+ invariant: "I2" | "I17",
99
+ ): void {
100
+ for (let i = 0; i < expected.length; i++) {
101
+ if (!Object.is(found[i], expected[i]) && found[i] !== expected[i]) {
102
+ throw viewError(view, member, i, invariant);
103
+ }
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Check that an array is a permutation of 0..length-1.
109
+ * @param view - the view name
110
+ * @param member - the member name
111
+ * @param perm - the array
112
+ */
113
+ function expectPermutation(view: string, member: string, perm: U32): void {
114
+ const seen = new Uint8Array(perm.length);
115
+ for (let i = 0; i < perm.length; i++) {
116
+ const p = perm[i];
117
+ if (p >= perm.length || seen[p] === 1) {
118
+ throw viewError(view, member, i, "I2");
119
+ }
120
+ seen[p] = 1;
121
+ }
122
+ }
123
+
124
+ /**
125
+ * outDegree: the row lengths.
126
+ * @param snapshot - the snapshot
127
+ * @param data - the carried array
128
+ */
129
+ export function checkOutDegree(snapshot: GraphSnapshot, data: U32): void {
130
+ expectSame("outDegree", "data", data, rowLengths(snapshot.rowPtr, snapshot.nodeCount), "I2");
131
+ }
132
+
133
+ /**
134
+ * inDegree (directed): the in-arc counts.
135
+ * @param facts - the core facts
136
+ * @param data - the carried array
137
+ */
138
+ export function checkInDegree(facts: CoreFacts, data: U32): void {
139
+ expectSame("inDegree", "data", data, facts.inDegree, "I2");
140
+ }
141
+
142
+ /**
143
+ * degree: outDegree + inDegree (directed) or outDegree + loops (undirected), design section 3.4.
144
+ * @param snapshot - the snapshot
145
+ * @param facts - the core facts
146
+ * @param data - the carried array
147
+ */
148
+ export function checkDegree(snapshot: GraphSnapshot, facts: CoreFacts, data: U32): void {
149
+ const out = rowLengths(snapshot.rowPtr, snapshot.nodeCount);
150
+ const add = snapshot.directed ? facts.inDegree : facts.loops;
151
+ for (let u = 0; u < out.length; u++) {
152
+ if (data[u] !== out[u] + add[u]) {
153
+ throw viewError("degree", "data", u, "I2");
154
+ }
155
+ }
156
+ }
157
+
158
+ /**
159
+ * selfLoopsPerNode: the loop arcs per row.
160
+ * @param facts - the core facts
161
+ * @param data - the carried array
162
+ */
163
+ export function checkSelfLoopsPerNode(facts: CoreFacts, data: U32): void {
164
+ expectSame("selfLoopsPerNode", "data", data, facts.loops, "I2");
165
+ }
166
+
167
+ /**
168
+ * selfLoopArcs: ascending arcs, each a loop; with the length fixed to selfLoopCount that is exact.
169
+ * @param snapshot - the snapshot
170
+ * @param facts - the core facts
171
+ * @param data - the carried array
172
+ */
173
+ export function checkSelfLoopArcs(snapshot: GraphSnapshot, facts: CoreFacts, data: U32): void {
174
+ const { colIdx, arcCount } = snapshot;
175
+ for (let i = 0; i < data.length; i++) {
176
+ const a = data[i];
177
+ if (a >= arcCount || colIdx[a] !== facts.arcRow[a] || (i > 0 && a <= data[i - 1])) {
178
+ throw viewError("selfLoopArcs", "data", i, "I2");
179
+ }
180
+ }
181
+ }
182
+
183
+ /**
184
+ * coo.src: the row of every arc.
185
+ * @param facts - the core facts
186
+ * @param src - the carried array
187
+ */
188
+ export function checkCooSrc(facts: CoreFacts, src: U32): void {
189
+ expectSame("coo", "src", src, facts.arcRow, "I2");
190
+ }
191
+
192
+ /**
193
+ * edgeList: `src[e]` is the row of `edgeToArc[e]`, `dst[e]` its target, `weights[e]` its weight.
194
+ * @param snapshot - the snapshot
195
+ * @param facts - the core facts
196
+ * @param src - the carried sources
197
+ * @param dst - the carried targets, or null when colIdx is aliased
198
+ * @param weights - the carried weights, or null when aliased or unweighted
199
+ */
200
+ export function checkEdgeList(
201
+ snapshot: GraphSnapshot,
202
+ facts: CoreFacts,
203
+ src: U32,
204
+ dst: U32 | null,
205
+ weights: F32 | null,
206
+ ): void {
207
+ const { edgeCount, edgeToArc, colIdx, arcCount } = snapshot;
208
+ const forward = snapshot.weights;
209
+ for (let e = 0; e < edgeCount; e++) {
210
+ const a = edgeToArc[e];
211
+ if (a >= arcCount || src[e] !== facts.arcRow[a]) {
212
+ throw viewError("edgeList", "src", e, "I2");
213
+ }
214
+ if (dst !== null && dst[e] !== colIdx[a]) {
215
+ throw viewError("edgeList", "dst", e, "I2");
216
+ }
217
+ if (weights !== null && forward !== null && !Object.is(weights[e], forward[a])) {
218
+ throw viewError("edgeList", "weights", e, "I17");
219
+ }
220
+ }
221
+ }
222
+
223
+ /**
224
+ * mate (undirected): an involution pairing the two arcs of every non-loop edge (invariant I7) and
225
+ * fixing every loop arc.
226
+ * @param snapshot - the snapshot
227
+ * @param facts - the core facts
228
+ * @param mate - the carried array
229
+ */
230
+ export function checkMate(snapshot: GraphSnapshot, facts: CoreFacts, mate: U32): void {
231
+ const { arcCount, arcToEdge, colIdx } = snapshot;
232
+ for (let a = 0; a < arcCount; a++) {
233
+ const m = mate[a];
234
+ const loop = colIdx[a] === facts.arcRow[a];
235
+ if (m >= arcCount || mate[m] !== a || arcToEdge[m] !== arcToEdge[a] || (m === a) !== loop) {
236
+ throw viewError("mate", "data", a, "I2");
237
+ }
238
+ }
239
+ }
240
+
241
+ /**
242
+ * degreeOrder / reverseDegreeOrder: a permutation ordered by non-increasing degree with ties in
243
+ * ascending node index, and the cuGraph tier offsets of design section 7.2.
244
+ * @param name - the view name
245
+ * @param degree - the degree of every node the order sorts by
246
+ * @param perm - the carried permutation
247
+ * @param segmentOffsets - the carried tier offsets
248
+ */
249
+ export function checkDegreeOrder(
250
+ name: "degreeOrder" | "reverseDegreeOrder",
251
+ degree: U32,
252
+ perm: U32,
253
+ segmentOffsets: U32,
254
+ ): void {
255
+ expectPermutation(name, "perm", perm);
256
+ let hi = 0;
257
+ let mid = 0;
258
+ let low = 0;
259
+ for (let i = 0; i < perm.length; i++) {
260
+ const d = degree[perm[i]];
261
+ if (i > 0) {
262
+ const previous = degree[perm[i - 1]];
263
+ if (d > previous || (d === previous && perm[i] < perm[i - 1])) {
264
+ throw viewError(name, "perm", i, "I2");
265
+ }
266
+ }
267
+ if (d >= DEGREE_TIER_HIGH) {
268
+ hi++;
269
+ } else if (d >= DEGREE_TIER_MID) {
270
+ mid++;
271
+ } else if (d >= 1) {
272
+ low++;
273
+ }
274
+ }
275
+ const expected = [0, hi, hi + mid, hi + mid + low, perm.length];
276
+ expectSame(name, "segmentOffsets", segmentOffsets, expected, "I2");
277
+ }
278
+
279
+ /**
280
+ * reverse (directed): the in-adjacency with rows sorted by source and ties by forward arc, `fwdArc`
281
+ * a permutation of the arcs, `colIdx` the sources, `weights` the forward weights gathered.
282
+ * @param snapshot - the snapshot
283
+ * @param facts - the core facts
284
+ * @param reverse - the carried view
285
+ */
286
+ export function checkReverse(snapshot: GraphSnapshot, facts: CoreFacts, reverse: ReverseView): void {
287
+ const { nodeCount, arcCount, colIdx } = snapshot;
288
+ const forward = snapshot.weights;
289
+ const { rowPtr, fwdArc } = reverse;
290
+ const revIdx = reverse.colIdx;
291
+ const revWeights = reverse.weights;
292
+ if (rowPtr[0] !== 0 || rowPtr[nodeCount] !== arcCount) {
293
+ throw viewError("reverse", "rowPtr", 0, "I2");
294
+ }
295
+ expectSame("reverse", "rowPtr", rowPtr, facts.inDegreePrefix(), "I2");
296
+ expectPermutation("reverse", "fwdArc", fwdArc);
297
+ for (let v = 0; v < nodeCount; v++) {
298
+ const end = rowPtr[v + 1];
299
+ for (let k = rowPtr[v]; k < end; k++) {
300
+ const a = fwdArc[k];
301
+ const source = facts.arcRow[a];
302
+ if (colIdx[a] !== v || revIdx[k] !== source) {
303
+ throw viewError("reverse", "colIdx", k, "I2");
304
+ }
305
+ if (k > rowPtr[v]) {
306
+ const previous = fwdArc[k - 1];
307
+ const previousSource = facts.arcRow[previous];
308
+ if (source < previousSource || (source === previousSource && a <= previous)) {
309
+ throw viewError("reverse", "fwdArc", k, "I2");
310
+ }
311
+ }
312
+ if (revWeights !== null && forward !== null && !Object.is(revWeights[k], forward[a])) {
313
+ throw viewError("reverse", "weights", k, "I17");
314
+ }
315
+ }
316
+ }
317
+ }
318
+
319
+ /**
320
+ * An f64 view: compared with the snapshot's own computation.
321
+ * @param name - the view name
322
+ * @param found - the carried array
323
+ * @param expected - the computed truth
324
+ */
325
+ export function checkF64View(name: string, found: F64, expected: F64): void {
326
+ expectSame(name, "data", found, expected, "I17");
327
+ }