@woosh/meep-engine 2.138.19 → 2.139.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 (496) hide show
  1. package/package.json +2 -1
  2. package/src/core/collection/PairUint32Map.d.ts +100 -0
  3. package/src/core/collection/PairUint32Map.d.ts.map +1 -0
  4. package/src/core/collection/PairUint32Map.js +321 -0
  5. package/src/core/collection/Uint32Map.d.ts +119 -0
  6. package/src/core/collection/Uint32Map.d.ts.map +1 -0
  7. package/src/core/collection/Uint32Map.js +345 -0
  8. package/src/core/collection/array/array_shuffle.d.ts +10 -3
  9. package/src/core/collection/array/array_shuffle.d.ts.map +1 -1
  10. package/src/core/collection/array/array_shuffle.js +27 -22
  11. package/src/core/collection/heap/FibonacciHeap.d.ts +195 -0
  12. package/src/core/collection/heap/FibonacciHeap.d.ts.map +1 -0
  13. package/src/core/collection/heap/FibonacciHeap.js +586 -0
  14. package/src/core/collection/heap/Uint32Heap.js +1 -1
  15. package/src/core/collection/heap/Uint32Heap4.d.ts +169 -0
  16. package/src/core/collection/heap/Uint32Heap4.d.ts.map +1 -0
  17. package/src/core/collection/heap/Uint32Heap4.js +490 -0
  18. package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts +27 -0
  19. package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts.map +1 -0
  20. package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +88 -0
  21. package/src/core/geom/3d/shape/BoxShape3D.d.ts +61 -0
  22. package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -0
  23. package/src/core/geom/3d/shape/BoxShape3D.js +158 -0
  24. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts +11 -0
  25. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
  26. package/src/core/geom/3d/shape/CapsuleShape3D.js +12 -0
  27. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts +37 -9
  28. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts.map +1 -1
  29. package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -98
  30. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts +10 -0
  31. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts.map +1 -1
  32. package/src/core/geom/3d/shape/UnitSphereShape3D.js +11 -0
  33. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts +61 -0
  34. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts.map +1 -0
  35. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +148 -0
  36. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts +39 -0
  37. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts.map +1 -0
  38. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +147 -0
  39. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts +15 -0
  40. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts.map +1 -0
  41. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +22 -0
  42. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts +2 -0
  43. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts.map +1 -0
  44. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.js +673 -0
  45. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts +26 -0
  46. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts.map +1 -0
  47. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +222 -0
  48. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts +34 -0
  49. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts.map +1 -0
  50. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -0
  51. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts +36 -0
  52. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts.map +1 -0
  53. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -0
  54. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts +33 -0
  55. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts.map +1 -0
  56. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -0
  57. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts +68 -0
  58. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts.map +1 -0
  59. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +365 -0
  60. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts +31 -0
  61. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts.map +1 -0
  62. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +112 -0
  63. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts +22 -0
  64. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts.map +1 -0
  65. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +55 -0
  66. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts +32 -0
  67. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts.map +1 -0
  68. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -0
  69. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts +22 -0
  70. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts.map +1 -1
  71. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +49 -0
  72. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts +134 -0
  73. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts.map +1 -1
  74. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +276 -3
  75. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +17 -0
  76. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -0
  77. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +135 -0
  78. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts +14 -0
  79. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts.map +1 -0
  80. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +177 -0
  81. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.d.ts.map +1 -1
  82. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +20 -4
  83. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts.map +1 -1
  84. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.js +5 -3
  85. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.d.ts.map +1 -1
  86. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +9 -0
  87. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.d.ts.map +1 -1
  88. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -45
  89. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.d.ts.map +1 -1
  90. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.js +7 -1
  91. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts +8 -6
  92. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts.map +1 -1
  93. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +8 -6
  94. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts +22 -0
  95. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts.map +1 -0
  96. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +73 -0
  97. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.d.ts.map +1 -1
  98. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.js +51 -1
  99. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts +10 -0
  100. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts.map +1 -0
  101. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -0
  102. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts +28 -0
  103. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts.map +1 -0
  104. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +227 -0
  105. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts +13 -0
  106. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts.map +1 -0
  107. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -0
  108. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts +11 -0
  109. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts.map +1 -0
  110. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +20 -0
  111. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts +20 -0
  112. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts.map +1 -0
  113. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +38 -0
  114. package/src/core/graph/csr/CSRGraph.d.ts +168 -0
  115. package/src/core/graph/csr/CSRGraph.d.ts.map +1 -0
  116. package/src/core/graph/csr/CSRGraph.js +319 -0
  117. package/src/core/graph/metis/cluster_mesh_metis.d.ts +12 -0
  118. package/src/core/graph/metis/cluster_mesh_metis.d.ts.map +1 -1
  119. package/src/core/graph/metis/cluster_mesh_metis.js +12 -0
  120. package/src/core/graph/metis/metis.d.ts +19 -0
  121. package/src/core/graph/metis/metis.d.ts.map +1 -1
  122. package/src/core/graph/metis/metis.js +20 -0
  123. package/src/core/graph/metis/metis_cluster_bs.d.ts +11 -0
  124. package/src/core/graph/metis/metis_cluster_bs.d.ts.map +1 -1
  125. package/src/core/graph/metis/metis_cluster_bs.js +11 -0
  126. package/src/core/graph/metis/metis_options.d.ts +17 -2
  127. package/src/core/graph/metis/metis_options.d.ts.map +1 -1
  128. package/src/core/graph/metis/metis_options.js +17 -2
  129. package/src/core/graph/metis/native/MetisGraph.d.ts +144 -0
  130. package/src/core/graph/metis/native/MetisGraph.d.ts.map +1 -0
  131. package/src/core/graph/metis/native/MetisGraph.js +212 -0
  132. package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts +72 -0
  133. package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts.map +1 -0
  134. package/src/core/graph/metis/native/bisection/BisectionScratch.js +101 -0
  135. package/src/core/graph/metis/native/bisection/bisect_graph.d.ts +37 -0
  136. package/src/core/graph/metis/native/bisection/bisect_graph.d.ts.map +1 -0
  137. package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -0
  138. package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts +15 -0
  139. package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts.map +1 -0
  140. package/src/core/graph/metis/native/bisection/compute_2way_params.js +84 -0
  141. package/src/core/graph/metis/native/bisection/fm_2way.d.ts +30 -0
  142. package/src/core/graph/metis/native/bisection/fm_2way.d.ts.map +1 -0
  143. package/src/core/graph/metis/native/bisection/fm_2way.js +290 -0
  144. package/src/core/graph/metis/native/bisection/grow_bisection.d.ts +23 -0
  145. package/src/core/graph/metis/native/bisection/grow_bisection.d.ts.map +1 -0
  146. package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -0
  147. package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts +28 -0
  148. package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts.map +1 -0
  149. package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -0
  150. package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts +20 -0
  151. package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts.map +1 -0
  152. package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -0
  153. package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts +24 -0
  154. package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts.map +1 -0
  155. package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -0
  156. package/src/core/graph/metis/native/coarsen/match_shem.d.ts +41 -0
  157. package/src/core/graph/metis/native/coarsen/match_shem.d.ts.map +1 -0
  158. package/src/core/graph/metis/native/coarsen/match_shem.js +175 -0
  159. package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts +24 -0
  160. package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts.map +1 -0
  161. package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -0
  162. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts +29 -0
  163. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts.map +1 -0
  164. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -0
  165. package/src/core/graph/metis/native/metis_partition_kway.d.ts +41 -0
  166. package/src/core/graph/metis/native/metis_partition_kway.d.ts.map +1 -0
  167. package/src/core/graph/metis/native/metis_partition_kway.js +126 -0
  168. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts +62 -0
  169. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts.map +1 -0
  170. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.js +261 -0
  171. package/src/core/graph/metis/native/refine/RefinementScratch.d.ts +45 -0
  172. package/src/core/graph/metis/native/refine/RefinementScratch.d.ts.map +1 -0
  173. package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -0
  174. package/src/core/graph/metis/native/refine/compute_kway_params.d.ts +18 -0
  175. package/src/core/graph/metis/native/refine/compute_kway_params.d.ts.map +1 -0
  176. package/src/core/graph/metis/native/refine/compute_kway_params.js +138 -0
  177. package/src/core/graph/metis/native/refine/fm_kway.d.ts +63 -0
  178. package/src/core/graph/metis/native/refine/fm_kway.d.ts.map +1 -0
  179. package/src/core/graph/metis/native/refine/fm_kway.js +462 -0
  180. package/src/core/graph/metis/native/refine/project_kway.d.ts +22 -0
  181. package/src/core/graph/metis/native/refine/project_kway.d.ts.map +1 -0
  182. package/src/core/graph/metis/native/refine/project_kway.js +43 -0
  183. package/src/core/graph/metis/native/refine/refine_kway.d.ts +34 -0
  184. package/src/core/graph/metis/native/refine/refine_kway.d.ts.map +1 -0
  185. package/src/core/graph/metis/native/refine/refine_kway.js +43 -0
  186. package/src/core/math/linalg/eigen/matrix_householder_in_place.d.ts +2 -2
  187. package/src/core/math/linalg/eigen/matrix_householder_in_place.js +2 -2
  188. package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts +6 -4
  189. package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts.map +1 -1
  190. package/src/core/math/linalg/eigen/matrix_qr_in_place.js +69 -23
  191. package/src/engine/EngineHarness.d.ts +3 -1
  192. package/src/engine/EngineHarness.d.ts.map +1 -1
  193. package/src/engine/EngineHarness.js +6 -4
  194. package/src/engine/control/first-person/DESIGN.md +30 -6
  195. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -0
  196. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +102 -9
  197. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
  198. package/src/engine/control/first-person/FirstPersonPlayerController.js +38 -3
  199. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +533 -4
  200. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
  201. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +315 -6
  202. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +220 -22
  203. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
  204. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +858 -241
  205. package/src/engine/control/first-person/TODO.md +127 -0
  206. package/src/engine/control/first-person/abilities/Ability.d.ts +101 -0
  207. package/src/engine/control/first-person/abilities/Ability.d.ts.map +1 -0
  208. package/src/engine/control/first-person/abilities/Ability.js +119 -0
  209. package/src/engine/control/first-person/abilities/AbilitySet.d.ts +86 -0
  210. package/src/engine/control/first-person/abilities/AbilitySet.d.ts.map +1 -0
  211. package/src/engine/control/first-person/abilities/AbilitySet.js +185 -0
  212. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts +62 -0
  213. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -0
  214. package/src/engine/control/first-person/abilities/LedgeGrab.js +199 -0
  215. package/src/engine/control/first-person/abilities/Mantle.d.ts +45 -0
  216. package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -0
  217. package/src/engine/control/first-person/abilities/Mantle.js +188 -0
  218. package/src/engine/control/first-person/abilities/Slide.d.ts +33 -0
  219. package/src/engine/control/first-person/abilities/Slide.d.ts.map +1 -0
  220. package/src/engine/control/first-person/abilities/Slide.js +158 -0
  221. package/src/engine/control/first-person/abilities/WallJump.d.ts +45 -0
  222. package/src/engine/control/first-person/abilities/WallJump.d.ts.map +1 -0
  223. package/src/engine/control/first-person/abilities/WallJump.js +131 -0
  224. package/src/engine/control/first-person/abilities/WallRun.d.ts +44 -0
  225. package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -0
  226. package/src/engine/control/first-person/abilities/WallRun.js +180 -0
  227. package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts +49 -0
  228. package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts.map +1 -0
  229. package/src/engine/control/first-person/composer/EyeOffsetStack.js +60 -0
  230. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts +100 -0
  231. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts.map +1 -0
  232. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.js +133 -0
  233. package/src/engine/control/first-person/mastery/DecisionPoint.d.ts +10 -0
  234. package/src/engine/control/first-person/mastery/DecisionPoint.d.ts.map +1 -0
  235. package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -0
  236. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts +61 -0
  237. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts.map +1 -0
  238. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.js +109 -0
  239. package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts +40 -0
  240. package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts.map +1 -0
  241. package/src/engine/control/first-person/mastery/MasteryEvaluator.js +45 -0
  242. package/src/engine/control/first-person/mastery/MasteryScore.d.ts +68 -0
  243. package/src/engine/control/first-person/mastery/MasteryScore.d.ts.map +1 -0
  244. package/src/engine/control/first-person/mastery/MasteryScore.js +100 -0
  245. package/src/engine/control/first-person/mastery/MasterySet.d.ts +60 -0
  246. package/src/engine/control/first-person/mastery/MasterySet.d.ts.map +1 -0
  247. package/src/engine/control/first-person/mastery/MasterySet.js +86 -0
  248. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts +58 -0
  249. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts.map +1 -0
  250. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.js +83 -0
  251. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts +69 -0
  252. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts.map +1 -0
  253. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.js +109 -0
  254. package/src/engine/control/first-person/math/Spring.d.ts +56 -0
  255. package/src/engine/control/first-person/math/Spring.d.ts.map +1 -0
  256. package/src/engine/control/first-person/math/Spring.js +71 -0
  257. package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts +26 -0
  258. package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts.map +1 -0
  259. package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -0
  260. package/src/engine/control/first-person/math/computeMassRatios.d.ts +35 -0
  261. package/src/engine/control/first-person/math/computeMassRatios.d.ts.map +1 -0
  262. package/src/engine/control/first-person/math/computeMassRatios.js +44 -0
  263. package/src/engine/control/first-person/pose/FirstPersonPose.d.ts +31 -1
  264. package/src/engine/control/first-person/pose/FirstPersonPose.d.ts.map +1 -1
  265. package/src/engine/control/first-person/pose/FirstPersonPose.js +49 -3
  266. package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts +7 -0
  267. package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts.map +1 -0
  268. package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -0
  269. package/src/engine/control/first-person/prototype_first_person_controller.js +550 -119
  270. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts +58 -0
  271. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts.map +1 -0
  272. package/src/engine/control/first-person/sensors/FirstPersonSensors.js +77 -0
  273. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts +80 -0
  274. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -0
  275. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +196 -0
  276. package/src/engine/control/first-person/test/buildTestPlayer.d.ts +20 -0
  277. package/src/engine/control/first-person/test/buildTestPlayer.d.ts.map +1 -0
  278. package/src/engine/control/first-person/test/buildTestPlayer.js +28 -0
  279. package/src/engine/ecs/EntityManager.d.ts +2 -2
  280. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  281. package/src/engine/ecs/EntityManager.js +13 -8
  282. package/src/engine/ecs/System.d.ts.map +1 -1
  283. package/src/engine/ecs/System.js +2 -2
  284. package/src/engine/graphics/camera/testClippingPlaneComputation.js +0 -2
  285. package/src/engine/graphics/ecs/light/Light.d.ts.map +1 -1
  286. package/src/engine/graphics/ecs/light/Light.js +27 -0
  287. package/src/engine/graphics/ecs/light/LightSystem.js +1 -1
  288. package/src/engine/graphics/ecs/path/PathDisplaySystem.d.ts.map +1 -1
  289. package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +0 -2
  290. package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +0 -2
  291. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +0 -2
  292. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +0 -2
  293. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +0 -2
  294. package/src/engine/navigation/grid/find_path_on_grid_astar.d.ts.map +1 -1
  295. package/src/engine/navigation/grid/find_path_on_grid_astar.js +11 -2
  296. package/src/engine/navigation/mesh/bt_mesh_face_find_path.d.ts.map +1 -1
  297. package/src/engine/navigation/mesh/bt_mesh_face_find_path.js +11 -1
  298. package/src/engine/physics/PLAN.md +236 -0
  299. package/src/engine/physics/body/BodyStorage.d.ts +187 -0
  300. package/src/engine/physics/body/BodyStorage.d.ts.map +1 -0
  301. package/src/engine/physics/body/BodyStorage.js +427 -0
  302. package/src/engine/physics/broadphase/PairList.d.ts +62 -0
  303. package/src/engine/physics/broadphase/PairList.d.ts.map +1 -0
  304. package/src/engine/physics/broadphase/PairList.js +97 -0
  305. package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts +30 -0
  306. package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts.map +1 -0
  307. package/src/engine/physics/broadphase/aabb_transform_oriented.js +93 -0
  308. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +16 -0
  309. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -0
  310. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +61 -0
  311. package/src/engine/physics/broadphase/generate_pairs.d.ts +38 -0
  312. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -0
  313. package/src/engine/physics/broadphase/generate_pairs.js +101 -0
  314. package/src/engine/physics/contact/ManifoldStore.d.ts +226 -0
  315. package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -0
  316. package/src/engine/physics/contact/ManifoldStore.js +499 -0
  317. package/src/engine/physics/ecs/BodyKind.d.ts +23 -0
  318. package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -0
  319. package/src/engine/physics/ecs/BodyKind.js +24 -0
  320. package/src/engine/physics/ecs/Collider.d.ts +98 -0
  321. package/src/engine/physics/ecs/Collider.d.ts.map +1 -0
  322. package/src/engine/physics/ecs/Collider.js +136 -0
  323. package/src/engine/physics/ecs/ColliderFlags.d.ts +14 -0
  324. package/src/engine/physics/ecs/ColliderFlags.d.ts.map +1 -0
  325. package/src/engine/physics/ecs/ColliderFlags.js +15 -0
  326. package/src/engine/physics/ecs/ColliderObserverSystem.d.ts +58 -0
  327. package/src/engine/physics/ecs/ColliderObserverSystem.d.ts.map +1 -0
  328. package/src/engine/physics/ecs/ColliderObserverSystem.js +103 -0
  329. package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts +25 -0
  330. package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts.map +1 -0
  331. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -0
  332. package/src/engine/physics/ecs/PhysicsEvents.d.ts +15 -0
  333. package/src/engine/physics/ecs/PhysicsEvents.d.ts.map +1 -0
  334. package/src/engine/physics/ecs/PhysicsEvents.js +16 -0
  335. package/src/engine/physics/ecs/PhysicsSystem.d.ts +520 -0
  336. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -0
  337. package/src/engine/physics/ecs/PhysicsSystem.js +1159 -0
  338. package/src/engine/physics/ecs/RigidBody.d.ts +197 -0
  339. package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -0
  340. package/src/engine/physics/ecs/RigidBody.js +240 -0
  341. package/src/engine/physics/ecs/RigidBodyFlags.d.ts +21 -0
  342. package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -0
  343. package/src/engine/physics/ecs/RigidBodyFlags.js +22 -0
  344. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts +28 -0
  345. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -0
  346. package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +81 -0
  347. package/src/engine/physics/ecs/SleepState.d.ts +11 -0
  348. package/src/engine/physics/ecs/SleepState.d.ts.map +1 -0
  349. package/src/engine/physics/ecs/SleepState.js +12 -0
  350. package/src/engine/physics/events/ContactEventBuffer.d.ts +46 -0
  351. package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -0
  352. package/src/engine/physics/events/ContactEventBuffer.js +83 -0
  353. package/src/engine/physics/events/diff_manifolds.d.ts +25 -0
  354. package/src/engine/physics/events/diff_manifolds.d.ts.map +1 -0
  355. package/src/engine/physics/events/diff_manifolds.js +50 -0
  356. package/src/engine/physics/fluid/FluidField.d.ts +294 -16
  357. package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
  358. package/src/engine/physics/fluid/FluidField.js +510 -66
  359. package/src/engine/physics/fluid/FluidSimulator.d.ts +188 -5
  360. package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
  361. package/src/engine/physics/fluid/FluidSimulator.js +455 -95
  362. package/src/engine/physics/fluid/SliceVisualiser.d.ts +29 -6
  363. package/src/engine/physics/fluid/SliceVisualiser.d.ts.map +1 -1
  364. package/src/engine/physics/fluid/SliceVisualiser.js +190 -165
  365. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +154 -0
  366. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts.map +1 -0
  367. package/src/engine/physics/fluid/ecs/FluidComponent.js +238 -0
  368. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts +45 -0
  369. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts.map +1 -0
  370. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -0
  371. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +107 -0
  372. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts.map +1 -0
  373. package/src/engine/physics/fluid/ecs/FluidSystem.js +278 -0
  374. package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts +62 -1
  375. package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts.map +1 -1
  376. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -6
  377. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts +17 -4
  378. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts.map +1 -1
  379. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +105 -12
  380. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts +43 -0
  381. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts.map +1 -0
  382. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +210 -0
  383. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts +62 -1
  384. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
  385. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +302 -8
  386. package/src/engine/physics/fluid/prototype.js +102 -91
  387. package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts +33 -0
  388. package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts.map +1 -0
  389. package/src/engine/physics/fluid/solver/optimal_sor_omega.js +41 -0
  390. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts +20 -5
  391. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts.map +1 -1
  392. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.js +60 -38
  393. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts +25 -4
  394. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts.map +1 -1
  395. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.js +93 -73
  396. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts +23 -0
  397. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts.map +1 -0
  398. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.js +60 -0
  399. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts +23 -0
  400. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts.map +1 -0
  401. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.js +68 -0
  402. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts +30 -0
  403. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts.map +1 -0
  404. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +66 -0
  405. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts +26 -0
  406. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts.map +1 -0
  407. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -0
  408. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts +30 -0
  409. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts.map +1 -0
  410. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -0
  411. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts +49 -0
  412. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts.map +1 -0
  413. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +126 -0
  414. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts +93 -0
  415. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts.map +1 -0
  416. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +424 -0
  417. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts +20 -0
  418. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts.map +1 -0
  419. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.js +83 -0
  420. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +26 -0
  421. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -0
  422. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +70 -0
  423. package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +1 -1
  424. package/src/engine/physics/gjk/expanding_polytope_algorithm.js +8 -10
  425. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +29 -0
  426. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -0
  427. package/src/engine/physics/inertia/world_inverse_inertia.js +79 -0
  428. package/src/engine/physics/integration/integrate_position.d.ts +16 -0
  429. package/src/engine/physics/integration/integrate_position.d.ts.map +1 -0
  430. package/src/engine/physics/integration/integrate_position.js +48 -0
  431. package/src/engine/physics/integration/integrate_velocity.d.ts +25 -0
  432. package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -0
  433. package/src/engine/physics/integration/integrate_velocity.js +79 -0
  434. package/src/engine/physics/integration/quat_integrate.d.ts +27 -0
  435. package/src/engine/physics/integration/quat_integrate.d.ts.map +1 -0
  436. package/src/engine/physics/integration/quat_integrate.js +62 -0
  437. package/src/engine/physics/island/IslandBuilder.d.ts +167 -0
  438. package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -0
  439. package/src/engine/physics/island/IslandBuilder.js +411 -0
  440. package/src/engine/physics/island/union_find.d.ts +51 -0
  441. package/src/engine/physics/island/union_find.d.ts.map +1 -0
  442. package/src/engine/physics/island/union_find.js +76 -0
  443. package/src/engine/physics/narrowphase/PosedShape.d.ts +59 -0
  444. package/src/engine/physics/narrowphase/PosedShape.d.ts.map +1 -0
  445. package/src/engine/physics/narrowphase/PosedShape.js +110 -0
  446. package/src/engine/physics/narrowphase/box_box_manifold.d.ts +32 -0
  447. package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -0
  448. package/src/engine/physics/narrowphase/box_box_manifold.js +543 -0
  449. package/src/engine/physics/narrowphase/capsule_contacts.d.ts +122 -0
  450. package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -0
  451. package/src/engine/physics/narrowphase/capsule_contacts.js +508 -0
  452. package/src/engine/physics/narrowphase/narrowphase_step.d.ts +11 -0
  453. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -0
  454. package/src/engine/physics/narrowphase/narrowphase_step.js +382 -0
  455. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts +38 -0
  456. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -0
  457. package/src/engine/physics/narrowphase/sphere_box_contact.js +130 -0
  458. package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts +26 -0
  459. package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts.map +1 -0
  460. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +51 -0
  461. package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts +83 -0
  462. package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts.map +1 -0
  463. package/src/engine/physics/queries/PhysicsSurfacePoint.js +100 -0
  464. package/src/engine/physics/queries/raycast.d.ts +20 -0
  465. package/src/engine/physics/queries/raycast.d.ts.map +1 -0
  466. package/src/engine/physics/queries/raycast.js +249 -0
  467. package/src/engine/physics/solver/friction_cone.d.ts +16 -0
  468. package/src/engine/physics/solver/friction_cone.d.ts.map +1 -0
  469. package/src/engine/physics/solver/friction_cone.js +37 -0
  470. package/src/engine/physics/solver/solve_contacts.d.ts +36 -0
  471. package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -0
  472. package/src/engine/physics/solver/solve_contacts.js +598 -0
  473. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts +0 -34
  474. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts.map +0 -1
  475. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.js +0 -66
  476. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts +0 -2
  477. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts.map +0 -1
  478. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.js +0 -54
  479. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts +0 -2
  480. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts.map +0 -1
  481. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.js +0 -26
  482. package/src/engine/ecs/components/Motion.d.ts +0 -21
  483. package/src/engine/ecs/components/Motion.d.ts.map +0 -1
  484. package/src/engine/ecs/components/Motion.js +0 -27
  485. package/src/engine/ecs/components/MotionSerializationAdapter.d.ts +0 -20
  486. package/src/engine/ecs/components/MotionSerializationAdapter.d.ts.map +0 -1
  487. package/src/engine/ecs/components/MotionSerializationAdapter.js +0 -26
  488. package/src/engine/ecs/systems/MotionSystem.d.ts +0 -9
  489. package/src/engine/ecs/systems/MotionSystem.d.ts.map +0 -1
  490. package/src/engine/ecs/systems/MotionSystem.js +0 -29
  491. package/src/engine/physics/fluid/Fluid.d.ts +0 -26
  492. package/src/engine/physics/fluid/Fluid.d.ts.map +0 -1
  493. package/src/engine/physics/fluid/Fluid.js +0 -221
  494. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts +0 -7
  495. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts.map +0 -1
  496. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.js +0 -8
@@ -0,0 +1,94 @@
1
+ import { create_coarse_graph } from "./create_coarse_graph.js";
2
+ import { match_shem } from "./match_shem.js";
3
+
4
+ /**
5
+ * If contraction shrinks the graph by less than this much in a level, further
6
+ * coarsening probably won't help. Matches the COARSEN_FRACTION threshold in
7
+ * libmetis/defs.h.
8
+ */
9
+ const MIN_USEFUL_CONTRACTION_RATIO = 0.85;
10
+
11
+ /**
12
+ * Safety cap: if we somehow keep contracting forever (shouldn't happen, but
13
+ * stops a runaway loop in pathological inputs).
14
+ */
15
+ const MAX_COARSENING_LEVELS = 32;
16
+
17
+ /**
18
+ * Drive the coarsening phase: repeatedly match + contract until the coarsest
19
+ * graph is small enough, or the contraction ratio drops below the threshold.
20
+ *
21
+ * On entry, `graph` is the original finest graph. On return, the result is the
22
+ * coarsest graph; walking `.finer_graph` repeatedly reaches the original.
23
+ *
24
+ * Mirrors `CoarsenGraph` from libmetis/coarsen.c.
25
+ *
26
+ * @param {import('../MetisGraph.js').MetisGraph} graph
27
+ * @param {{random: function():number, coarsen_until_vertex_count: number}} opts
28
+ * `coarsen_until_vertex_count`: stop coarsening once vertex_count drops at or
29
+ * below this. METIS uses `max(vertex_count / (20·log2(nparts)), 30·nparts)`.
30
+ * @returns {import('../MetisGraph.js').MetisGraph} the coarsest graph
31
+ */
32
+ export function coarsen_graph(graph, opts) {
33
+ const random = opts.random;
34
+ const coarsen_until_vertex_count = opts.coarsen_until_vertex_count;
35
+
36
+ let current_level = graph;
37
+ let remaining_levels = MAX_COARSENING_LEVELS;
38
+
39
+ // Three vertex_count-sized buffers reused across every coarsening level.
40
+ // Sized to the finest graph's vertex_count; subsequent (coarser) levels
41
+ // only need a prefix. match_shem either refills the active range itself
42
+ // (`partner_of_vertex`) or overwrites every entry it reads
43
+ // (`visit_order` and `sort_key_degree`), so stale tail data is harmless.
44
+ const partner_of_vertex = new Uint32Array(graph.vertex_count);
45
+ const visit_order = new Uint32Array(graph.vertex_count);
46
+ const sort_key_degree = new Uint32Array(graph.vertex_count);
47
+
48
+ while (remaining_levels-- > 0) {
49
+
50
+ // Cap a single coarse vertex's weight at ~1.5x what one balanced
51
+ // partition could hold at the coarsest level. METIS uses
52
+ // 1.5 * total_vertex_weight / coarsen_until_vertex_count.
53
+ // The total is preserved across coarsening, so recomputing per level
54
+ // is cheap and follows the size threshold naturally.
55
+ const max_coarse_vertex_weight = Math.max(
56
+ 1,
57
+ Math.ceil(1.5 * current_level.total_vertex_weight / coarsen_until_vertex_count)
58
+ );
59
+
60
+ const coarse_vertex_count = match_shem(
61
+ current_level,
62
+ random,
63
+ max_coarse_vertex_weight,
64
+ partner_of_vertex,
65
+ visit_order,
66
+ sort_key_degree
67
+ );
68
+
69
+ if (coarse_vertex_count >= current_level.vertex_count) {
70
+ // Matching collapsed nothing — graph is too irregular to benefit
71
+ // from another level. Stop.
72
+ break;
73
+ }
74
+
75
+ const coarser = create_coarse_graph(current_level, coarse_vertex_count, partner_of_vertex);
76
+ const contraction_ratio = coarser.vertex_count / current_level.vertex_count;
77
+
78
+ current_level = coarser;
79
+
80
+ if (current_level.vertex_count <= coarsen_until_vertex_count) {
81
+ break;
82
+ }
83
+ if (contraction_ratio > MIN_USEFUL_CONTRACTION_RATIO) {
84
+ // Contraction stalled; further levels offer diminishing returns.
85
+ break;
86
+ }
87
+ if (current_level.adjacency_length < current_level.vertex_count / 2) {
88
+ // Graph is too sparse to benefit from another coarsening pass.
89
+ break;
90
+ }
91
+ }
92
+
93
+ return current_level;
94
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Contract a matched graph into its coarse counterpart.
3
+ *
4
+ * Each matched pair (vertex, partner) collapses to a single coarse vertex whose
5
+ * weight is the sum of both endpoints. Parallel edges to the same coarse
6
+ * neighbour merge into one edge with summed weight. Self-loops produced by
7
+ * collapsing the matched pair itself are dropped.
8
+ *
9
+ * Mirrors `CreateCoarseGraphNoMask` from libmetis/coarsen.c. The masked variant
10
+ * (open-addressing hash with a power-of-two mask) is skipped — the unmasked
11
+ * flat-htable path is fast enough at our scale and is simpler.
12
+ *
13
+ * Precondition: `match_shem` has run and produced `graph.coarse_vertex_map`
14
+ * indexed such that processing vertices in order v=0..vertex_count increments
15
+ * through coarse ids 0..coarse_vertex_count-1.
16
+ *
17
+ * @param {MetisGraph} graph fine graph (input)
18
+ * @param {number} coarse_vertex_count
19
+ * @param {Uint32Array} partner_of_vertex `[v]` = match partner of v, or v itself if alone
20
+ * @returns {MetisGraph} the coarse graph (also assigned to `graph.coarser_graph`)
21
+ */
22
+ export function create_coarse_graph(graph: MetisGraph, coarse_vertex_count: number, partner_of_vertex: Uint32Array): MetisGraph;
23
+ import { MetisGraph } from "../MetisGraph.js";
24
+ //# sourceMappingURL=create_coarse_graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_coarse_graph.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/graph/metis/native/coarsen/create_coarse_graph.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,2CALW,UAAU,uBACV,MAAM,qBACN,WAAW,GACT,UAAU,CAuItB;2BA5J0B,kBAAkB"}
@@ -0,0 +1,158 @@
1
+ import { assert } from "../../../../assert.js";
2
+ import { MetisGraph } from "../MetisGraph.js";
3
+
4
+ /**
5
+ * Contract a matched graph into its coarse counterpart.
6
+ *
7
+ * Each matched pair (vertex, partner) collapses to a single coarse vertex whose
8
+ * weight is the sum of both endpoints. Parallel edges to the same coarse
9
+ * neighbour merge into one edge with summed weight. Self-loops produced by
10
+ * collapsing the matched pair itself are dropped.
11
+ *
12
+ * Mirrors `CreateCoarseGraphNoMask` from libmetis/coarsen.c. The masked variant
13
+ * (open-addressing hash with a power-of-two mask) is skipped — the unmasked
14
+ * flat-htable path is fast enough at our scale and is simpler.
15
+ *
16
+ * Precondition: `match_shem` has run and produced `graph.coarse_vertex_map`
17
+ * indexed such that processing vertices in order v=0..vertex_count increments
18
+ * through coarse ids 0..coarse_vertex_count-1.
19
+ *
20
+ * @param {MetisGraph} graph fine graph (input)
21
+ * @param {number} coarse_vertex_count
22
+ * @param {Uint32Array} partner_of_vertex `[v]` = match partner of v, or v itself if alone
23
+ * @returns {MetisGraph} the coarse graph (also assigned to `graph.coarser_graph`)
24
+ */
25
+ export function create_coarse_graph(graph, coarse_vertex_count, partner_of_vertex) {
26
+
27
+ const vertex_count = graph.vertex_count;
28
+ const edge_addresses = graph.edge_addresses;
29
+ const adjacency = graph.adjacency;
30
+ const edge_weights = graph.edge_weights;
31
+ const vertex_weights = graph.vertex_weights;
32
+ const coarse_vertex_map = graph.coarse_vertex_map;
33
+
34
+ assert.equal(coarse_vertex_map !== null, true, 'graph.coarse_vertex_map must be set by match_shem before contraction');
35
+
36
+ // Worst-case sizing: every edge of the fine graph survives unmerged. The
37
+ // actual edge count is known only after the merge pass, so we trim at the end.
38
+ const coarse_graph = new MetisGraph(coarse_vertex_count, graph.adjacency_length);
39
+ const coarse_edge_addresses = coarse_graph.edge_addresses;
40
+ const coarse_adjacency = coarse_graph.adjacency;
41
+ const coarse_edge_weights = coarse_graph.edge_weights;
42
+ const coarse_vertex_weights = coarse_graph.vertex_weights;
43
+
44
+ // For each coarse neighbour id k that we've already seen while building the
45
+ // current super-vertex's adjacency list, `coarse_nbr_position[k]` is its
46
+ // slot in our local section of coarse_adjacency. -1 = not seen yet.
47
+ // Reset only at the touched entries per vertex (O(degree)) rather than
48
+ // wholesale (O(coarse_vertex_count)).
49
+ const coarse_nbr_position = new Int32Array(coarse_vertex_count);
50
+ coarse_nbr_position.fill(-1);
51
+
52
+ let next_coarse_id = 0; // must equal coarse_vertex_map[vertex] when we process it
53
+ let coarse_edge_cursor = 0; // running write position into coarse_adjacency / coarse_edge_weights
54
+ coarse_edge_addresses[0] = 0;
55
+
56
+ for (let vertex = 0; vertex < vertex_count; vertex++) {
57
+ const partner = partner_of_vertex[vertex];
58
+ if (partner < vertex) {
59
+ // Already handled when we processed `partner` earlier in this loop.
60
+ continue;
61
+ }
62
+
63
+ assert.equal(
64
+ coarse_vertex_map[vertex], next_coarse_id,
65
+ 'coarse_vertex_map[v] should equal running coarse id counter; match_shem renumbering was skipped or wrong'
66
+ );
67
+
68
+ coarse_vertex_weights[next_coarse_id] = vertex_weights[vertex];
69
+
70
+ let coarse_nbr_count_for_this_vertex = 0;
71
+
72
+ // ----- Merge vertex's neighbours into the coarse adjacency -----
73
+ {
74
+ const edge_start = edge_addresses[vertex];
75
+ const edge_end = edge_addresses[vertex + 1];
76
+ for (let edge_offset = edge_start; edge_offset < edge_end; edge_offset++) {
77
+ const coarse_neighbor = coarse_vertex_map[adjacency[edge_offset]];
78
+ const existing_position = coarse_nbr_position[coarse_neighbor];
79
+ if (existing_position === -1) {
80
+ coarse_adjacency[coarse_edge_cursor + coarse_nbr_count_for_this_vertex] = coarse_neighbor;
81
+ coarse_edge_weights[coarse_edge_cursor + coarse_nbr_count_for_this_vertex] = edge_weights[edge_offset];
82
+ coarse_nbr_position[coarse_neighbor] = coarse_nbr_count_for_this_vertex;
83
+ coarse_nbr_count_for_this_vertex++;
84
+ } else {
85
+ coarse_edge_weights[coarse_edge_cursor + existing_position] += edge_weights[edge_offset];
86
+ }
87
+ }
88
+ }
89
+
90
+ if (vertex !== partner) {
91
+ // ----- Add the partner's weight and merge its neighbours too -----
92
+ coarse_vertex_weights[next_coarse_id] += vertex_weights[partner];
93
+
94
+ const edge_start = edge_addresses[partner];
95
+ const edge_end = edge_addresses[partner + 1];
96
+ for (let edge_offset = edge_start; edge_offset < edge_end; edge_offset++) {
97
+ const coarse_neighbor = coarse_vertex_map[adjacency[edge_offset]];
98
+ const existing_position = coarse_nbr_position[coarse_neighbor];
99
+ if (existing_position === -1) {
100
+ coarse_adjacency[coarse_edge_cursor + coarse_nbr_count_for_this_vertex] = coarse_neighbor;
101
+ coarse_edge_weights[coarse_edge_cursor + coarse_nbr_count_for_this_vertex] = edge_weights[edge_offset];
102
+ coarse_nbr_position[coarse_neighbor] = coarse_nbr_count_for_this_vertex;
103
+ coarse_nbr_count_for_this_vertex++;
104
+ } else {
105
+ coarse_edge_weights[coarse_edge_cursor + existing_position] += edge_weights[edge_offset];
106
+ }
107
+ }
108
+
109
+ // The (vertex, partner) edge maps to (next_coarse_id, next_coarse_id):
110
+ // a self-loop. Drop it by swap-with-last.
111
+ const self_loop_position = coarse_nbr_position[next_coarse_id];
112
+ if (self_loop_position !== -1) {
113
+ const last_position = coarse_nbr_count_for_this_vertex - 1;
114
+ if (self_loop_position !== last_position) {
115
+ const moved_neighbor = coarse_adjacency[coarse_edge_cursor + last_position];
116
+ coarse_adjacency[coarse_edge_cursor + self_loop_position] = moved_neighbor;
117
+ coarse_edge_weights[coarse_edge_cursor + self_loop_position] = coarse_edge_weights[coarse_edge_cursor + last_position];
118
+ coarse_nbr_position[moved_neighbor] = self_loop_position;
119
+ }
120
+ coarse_nbr_count_for_this_vertex = last_position;
121
+ }
122
+ }
123
+
124
+ // Reset coarse_nbr_position for just the slots we touched.
125
+ for (let local_position = 0; local_position < coarse_nbr_count_for_this_vertex; local_position++) {
126
+ coarse_nbr_position[coarse_adjacency[coarse_edge_cursor + local_position]] = -1;
127
+ }
128
+ // Self-loop slot may have been populated and popped without leaving a
129
+ // trace in the loop above; clear unconditionally so subsequent vertices
130
+ // don't see stale state.
131
+ coarse_nbr_position[next_coarse_id] = -1;
132
+
133
+ coarse_edge_cursor += coarse_nbr_count_for_this_vertex;
134
+ next_coarse_id++;
135
+ coarse_edge_addresses[next_coarse_id] = coarse_edge_cursor;
136
+ }
137
+
138
+ assert.equal(next_coarse_id, coarse_vertex_count, 'final coarse id counter must equal coarse_vertex_count');
139
+
140
+ // Record the actual adjacency length, but DON'T truncate the underlying
141
+ // buffer. Truncation here would allocate a fresh shared buffer and bulk-copy
142
+ // four typed arrays into it just to shrink — at every coarsening level — and
143
+ // the immediate caller doesn't need the savings; the coarse graph is
144
+ // short-lived relative to the overall partitioning call.
145
+ //
146
+ // The unused tail of `adjacency` and `edge_weights` is harmless: downstream
147
+ // code consistently uses `adjacency_length` as the source of truth (never
148
+ // `.length`). Callers that genuinely need the memory back can call
149
+ // `truncate_adjacency` themselves once they're done filling the graph.
150
+ coarse_graph.adjacency_length = coarse_edge_cursor;
151
+ coarse_graph.refresh_total_vertex_weight();
152
+
153
+ // Link the levels for later projection back down.
154
+ coarse_graph.finer_graph = graph;
155
+ graph.coarser_graph = coarse_graph;
156
+
157
+ return coarse_graph;
158
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Sorted Heavy-Edge Matching.
3
+ *
4
+ * Visits vertices in random order biased toward lower degree first, and for
5
+ * each unmatched vertex pairs it with the unmatched neighbour sharing the
6
+ * heaviest edge weight (subject to a coarse-vertex weight cap).
7
+ *
8
+ * Outputs:
9
+ * - `graph.coarse_vertex_map[v]` = id of the coarse vertex that vertex v
10
+ * collapses into. Numbered so that iterating v=0..vertex_count walks coarse
11
+ * ids 0..coarse_vertex_count-1 in order — this property is required by
12
+ * `create_coarse_graph`.
13
+ * - `partner_of_vertex[v]` = the partner of vertex v (or v itself if it ended
14
+ * up alone in the matching). Caller-provided buffer, filled in place.
15
+ * - returns `coarse_vertex_count`, the number of coarse vertices created.
16
+ *
17
+ * Mirrors `Match_SHEM` from libmetis/coarsen.c, single-constraint branch.
18
+ * The 2-hop matching escape hatch is intentionally skipped — it's a degeneracy
19
+ * recovery for graphs with many isolated/low-degree vertices that's not on the
20
+ * critical path; can add later if cluster quality bites.
21
+ *
22
+ * @param {import('../MetisGraph.js').MetisGraph} graph
23
+ * @param {function():number} random seeded RNG
24
+ * @param {number} max_coarse_vertex_weight cap on the combined weight of a
25
+ * matched pair; vertices whose own weight already exceeds this are forced
26
+ * into singleton coarse vertices
27
+ * @param {Uint32Array} partner_of_vertex caller-provided buffer of length
28
+ * `>= graph.vertex_count`. Will be filled with each vertex's match partner
29
+ * (or its own id if it ended up unmatched). The first `graph.vertex_count`
30
+ * entries are clobbered; any tail beyond that is left untouched.
31
+ * @param {Uint32Array} visit_order caller-provided scratch of length
32
+ * `>= graph.vertex_count`. Used as the (random-shuffled, degree-sorted)
33
+ * visitation order during matching. Contents on entry are ignored;
34
+ * contents on return are undefined.
35
+ * @param {Uint32Array} sort_key_degree caller-provided scratch of length
36
+ * `>= graph.vertex_count`. Holds the per-vertex degree buckets used to sort
37
+ * `visit_order`. Contents on entry are ignored; contents on return are undefined.
38
+ * @returns {number} `coarse_vertex_count`
39
+ */
40
+ export function match_shem(graph: import('../MetisGraph.js').MetisGraph, random: () => number, max_coarse_vertex_weight: number, partner_of_vertex: Uint32Array, visit_order: Uint32Array, sort_key_degree: Uint32Array): number;
41
+ //# sourceMappingURL=match_shem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"match_shem.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/graph/metis/native/coarsen/match_shem.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,kCAlBW,OAAO,kBAAkB,EAAE,UAAU,gBAC1B,MAAM,4BACjB,MAAM,qBAGN,WAAW,eAIX,WAAW,mBAIX,WAAW,GAGT,MAAM,CAoIlB"}
@@ -0,0 +1,175 @@
1
+ import { array_quick_sort_by_lookup_uint } from "../../../../collection/array/array_quick_sort_by_lookup_uint.js";
2
+ import { array_shuffle } from "../../../../collection/array/array_shuffle.js";
3
+
4
+ const UNMATCHED = 0xFFFFFFFF;
5
+
6
+ /**
7
+ * Sorted Heavy-Edge Matching.
8
+ *
9
+ * Visits vertices in random order biased toward lower degree first, and for
10
+ * each unmatched vertex pairs it with the unmatched neighbour sharing the
11
+ * heaviest edge weight (subject to a coarse-vertex weight cap).
12
+ *
13
+ * Outputs:
14
+ * - `graph.coarse_vertex_map[v]` = id of the coarse vertex that vertex v
15
+ * collapses into. Numbered so that iterating v=0..vertex_count walks coarse
16
+ * ids 0..coarse_vertex_count-1 in order — this property is required by
17
+ * `create_coarse_graph`.
18
+ * - `partner_of_vertex[v]` = the partner of vertex v (or v itself if it ended
19
+ * up alone in the matching). Caller-provided buffer, filled in place.
20
+ * - returns `coarse_vertex_count`, the number of coarse vertices created.
21
+ *
22
+ * Mirrors `Match_SHEM` from libmetis/coarsen.c, single-constraint branch.
23
+ * The 2-hop matching escape hatch is intentionally skipped — it's a degeneracy
24
+ * recovery for graphs with many isolated/low-degree vertices that's not on the
25
+ * critical path; can add later if cluster quality bites.
26
+ *
27
+ * @param {import('../MetisGraph.js').MetisGraph} graph
28
+ * @param {function():number} random seeded RNG
29
+ * @param {number} max_coarse_vertex_weight cap on the combined weight of a
30
+ * matched pair; vertices whose own weight already exceeds this are forced
31
+ * into singleton coarse vertices
32
+ * @param {Uint32Array} partner_of_vertex caller-provided buffer of length
33
+ * `>= graph.vertex_count`. Will be filled with each vertex's match partner
34
+ * (or its own id if it ended up unmatched). The first `graph.vertex_count`
35
+ * entries are clobbered; any tail beyond that is left untouched.
36
+ * @param {Uint32Array} visit_order caller-provided scratch of length
37
+ * `>= graph.vertex_count`. Used as the (random-shuffled, degree-sorted)
38
+ * visitation order during matching. Contents on entry are ignored;
39
+ * contents on return are undefined.
40
+ * @param {Uint32Array} sort_key_degree caller-provided scratch of length
41
+ * `>= graph.vertex_count`. Holds the per-vertex degree buckets used to sort
42
+ * `visit_order`. Contents on entry are ignored; contents on return are undefined.
43
+ * @returns {number} `coarse_vertex_count`
44
+ */
45
+ export function match_shem(
46
+ graph,
47
+ random,
48
+ max_coarse_vertex_weight,
49
+ partner_of_vertex,
50
+ visit_order,
51
+ sort_key_degree
52
+ ) {
53
+
54
+ const vertex_count = graph.vertex_count;
55
+ const edge_addresses = graph.edge_addresses;
56
+ const adjacency = graph.adjacency;
57
+ const edge_weights = graph.edge_weights;
58
+ const vertex_weights = graph.vertex_weights;
59
+
60
+ const coarse_vertex_map = graph.coarse_vertex_map !== null && graph.coarse_vertex_map.length === vertex_count
61
+ ? graph.coarse_vertex_map
62
+ : new Uint32Array(vertex_count);
63
+ graph.coarse_vertex_map = coarse_vertex_map;
64
+
65
+ partner_of_vertex.fill(UNMATCHED, 0, vertex_count);
66
+
67
+ if (vertex_count === 0) {
68
+ return 0;
69
+ }
70
+
71
+ // Visitation order: random permutation, then sorted ascending by capped
72
+ // degree so low-degree (harder to match) vertices get first pick.
73
+ for (let v = 0; v < vertex_count; v++) {
74
+ visit_order[v] = v;
75
+ }
76
+ array_shuffle(random, visit_order, vertex_count);
77
+
78
+ // Visitation order key: bucket vertices by sqrt(1 + degree), capped at
79
+ // 4× average degree. Mirrors master's heuristic — much more permissive
80
+ // than 5.1.0's raw-degree + 0.7× cap. Effect: visitation order is roughly
81
+ // logarithmic in degree, so isolated high-degree outliers don't dominate
82
+ // the ordering. For graphs with degree variance (real meshes have these),
83
+ // this gives more uniform matching coverage.
84
+ const total_adjacency_length = edge_addresses[vertex_count];
85
+ const average_degree = Math.max(1, Math.floor(4.0 * (total_adjacency_length / vertex_count)));
86
+
87
+ for (let v = 0; v < vertex_count; v++) {
88
+ const degree = edge_addresses[v + 1] - edge_addresses[v];
89
+ const bucket = Math.floor(Math.sqrt(1 + degree));
90
+ sort_key_degree[v] = bucket > average_degree ? average_degree : bucket;
91
+ }
92
+
93
+ if (vertex_count > 1) {
94
+ array_quick_sort_by_lookup_uint(visit_order, sort_key_degree, 0, vertex_count - 1);
95
+ }
96
+
97
+ // --- Pass 1: matching --------------------------------------------------
98
+ let next_unmatched_search_start = 0;
99
+
100
+ for (let visit_position = 0; visit_position < vertex_count; visit_position++) {
101
+ const vertex = visit_order[visit_position];
102
+
103
+ if (partner_of_vertex[vertex] !== UNMATCHED) {
104
+ continue;
105
+ }
106
+
107
+ let best_partner = vertex; // self-match if no candidate is found
108
+ let best_partner_edge_weight = -1;
109
+
110
+ if (vertex_weights[vertex] < max_coarse_vertex_weight) {
111
+
112
+ const edge_start = edge_addresses[vertex];
113
+ const edge_end = edge_addresses[vertex + 1];
114
+
115
+ if (edge_start === edge_end) {
116
+ // Isolated vertex: forward-scan visit_order for any other unmatched
117
+ // vertex. Mirrors METIS's "island" path, which ignores the weight cap
118
+ // for these pairings.
119
+ if (next_unmatched_search_start < visit_position) {
120
+ next_unmatched_search_start = visit_position;
121
+ }
122
+ next_unmatched_search_start++;
123
+ while (next_unmatched_search_start < vertex_count) {
124
+ const candidate = visit_order[next_unmatched_search_start];
125
+ if (partner_of_vertex[candidate] === UNMATCHED) {
126
+ best_partner = candidate;
127
+ break;
128
+ }
129
+ next_unmatched_search_start++;
130
+ }
131
+ } else {
132
+ // Heavy-edge: pick the unmatched neighbour whose edge has the
133
+ // greatest weight, subject to the coarse-weight cap.
134
+ for (let edge_offset = edge_start; edge_offset < edge_end; edge_offset++) {
135
+ const neighbor = adjacency[edge_offset];
136
+ const weight = edge_weights[edge_offset];
137
+ if (
138
+ partner_of_vertex[neighbor] === UNMATCHED &&
139
+ weight > best_partner_edge_weight &&
140
+ vertex_weights[vertex] + vertex_weights[neighbor] <= max_coarse_vertex_weight
141
+ ) {
142
+ best_partner = neighbor;
143
+ best_partner_edge_weight = weight;
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ if (best_partner !== vertex) {
150
+ partner_of_vertex[vertex] = best_partner;
151
+ partner_of_vertex[best_partner] = vertex;
152
+ }
153
+ // else: leave UNMATCHED; the renumbering pass below will self-match it.
154
+ }
155
+
156
+ // --- Pass 2: renumber coarse_vertex_map in vertex-id order -------------
157
+ // `create_coarse_graph` requires that when it processes vertices in order
158
+ // v = 0..vertex_count, coarse_vertex_map[v] equals the running count of
159
+ // coarse vertices produced so far. Also self-match anything still UNMATCHED.
160
+ let coarse_vertex_count = 0;
161
+ for (let vertex = 0; vertex < vertex_count; vertex++) {
162
+ const partner = partner_of_vertex[vertex];
163
+ if (partner === UNMATCHED) {
164
+ partner_of_vertex[vertex] = vertex;
165
+ coarse_vertex_map[vertex] = coarse_vertex_count;
166
+ coarse_vertex_count++;
167
+ } else if (vertex <= partner) {
168
+ coarse_vertex_map[vertex] = coarse_vertex_count;
169
+ coarse_vertex_map[partner] = coarse_vertex_count;
170
+ coarse_vertex_count++;
171
+ }
172
+ }
173
+
174
+ return coarse_vertex_count;
175
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Initial k-way partition via simultaneous BFS from k random seed vertices.
3
+ *
4
+ * Each seed grows its partition outward by FIFO BFS, claiming any neighbour
5
+ * that hasn't been claimed yet. A partition stops growing once its accumulated
6
+ * vertex weight crosses the per-partition target. Any vertices left unassigned
7
+ * — typically because their component was fully consumed by a partition that
8
+ * then hit its cap, or because the graph has more than k components — get
9
+ * assigned to whichever partition is currently lightest.
10
+ *
11
+ * This is a quality-vs-simplicity trade-off relative to METIS's recursive
12
+ * bisection on the coarsest graph. Bisection produces lower edge cuts but
13
+ * costs roughly 5× the code. FM uncoarsening recovers a large fraction of the
14
+ * quality difference, so we ship BFS-growth first and revisit if needed.
15
+ *
16
+ * Writes to `graph.vertex_partition[]` and `graph.partition_weights[]`. Both
17
+ * must already be allocated (call `graph.allocate_partition_state(partition_count)`).
18
+ *
19
+ * @param {import('../MetisGraph.js').MetisGraph} graph the coarsest graph
20
+ * @param {number} partition_count
21
+ * @param {function():number} random
22
+ */
23
+ export function initial_kway_bfs(graph: import('../MetisGraph.js').MetisGraph, partition_count: number, random: () => number): void;
24
+ //# sourceMappingURL=initial_kway_bfs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initial_kway_bfs.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/graph/metis/native/initial/initial_kway_bfs.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wCAJW,OAAO,kBAAkB,EAAE,UAAU,mBACrC,MAAM,gBACK,MAAM,QAyF3B"}
@@ -0,0 +1,122 @@
1
+ import { array_shuffle } from "../../../../collection/array/array_shuffle.js";
2
+
3
+ const UNASSIGNED = 0xFFFFFFFF;
4
+
5
+ /**
6
+ * Fractional overshoot allowed for a partition's weight during BFS growth.
7
+ * Once a partition crosses `target_weight × this`, it stops claiming new
8
+ * neighbours. A small slack avoids starving a partition that hits the target
9
+ * exactly mid-step.
10
+ */
11
+ const GROWTH_OVERSHOOT_FRACTION = 1.05;
12
+
13
+ /**
14
+ * Initial k-way partition via simultaneous BFS from k random seed vertices.
15
+ *
16
+ * Each seed grows its partition outward by FIFO BFS, claiming any neighbour
17
+ * that hasn't been claimed yet. A partition stops growing once its accumulated
18
+ * vertex weight crosses the per-partition target. Any vertices left unassigned
19
+ * — typically because their component was fully consumed by a partition that
20
+ * then hit its cap, or because the graph has more than k components — get
21
+ * assigned to whichever partition is currently lightest.
22
+ *
23
+ * This is a quality-vs-simplicity trade-off relative to METIS's recursive
24
+ * bisection on the coarsest graph. Bisection produces lower edge cuts but
25
+ * costs roughly 5× the code. FM uncoarsening recovers a large fraction of the
26
+ * quality difference, so we ship BFS-growth first and revisit if needed.
27
+ *
28
+ * Writes to `graph.vertex_partition[]` and `graph.partition_weights[]`. Both
29
+ * must already be allocated (call `graph.allocate_partition_state(partition_count)`).
30
+ *
31
+ * @param {import('../MetisGraph.js').MetisGraph} graph the coarsest graph
32
+ * @param {number} partition_count
33
+ * @param {function():number} random
34
+ */
35
+ export function initial_kway_bfs(graph, partition_count, random) {
36
+ const vertex_count = graph.vertex_count;
37
+ const edge_addresses = graph.edge_addresses;
38
+ const adjacency = graph.adjacency;
39
+ const vertex_weights = graph.vertex_weights;
40
+ const total_vertex_weight = graph.total_vertex_weight;
41
+ const vertex_partition = graph.vertex_partition;
42
+ const partition_weights = graph.partition_weights;
43
+
44
+ vertex_partition.fill(UNASSIGNED);
45
+ partition_weights.fill(0);
46
+
47
+ if (vertex_count === 0 || partition_count === 0) {
48
+ return;
49
+ }
50
+
51
+ const partition_weight_cap = Math.ceil((total_vertex_weight / partition_count) * GROWTH_OVERSHOOT_FRACTION);
52
+
53
+ // Pick k distinct seeds by shuffling all vertex ids and taking the prefix.
54
+ // Cheaper alternatives exist for k << vertex_count but this is simple and
55
+ // unambiguously correct.
56
+ const shuffled_vertex_ids = new Uint32Array(vertex_count);
57
+ for (let v = 0; v < vertex_count; v++) {
58
+ shuffled_vertex_ids[v] = v;
59
+ }
60
+ array_shuffle(random, shuffled_vertex_ids);
61
+
62
+ // Shared (vertex, partition) FIFO queue. We claim a vertex by writing to
63
+ // vertex_partition at push time, so every vertex is pushed at most once
64
+ // and 2*vertex_count bounds the queue size.
65
+ const bfs_queue = new Uint32Array(vertex_count * 2);
66
+ let queue_head = 0;
67
+ let queue_tail = 0;
68
+
69
+ const seed_count = Math.min(partition_count, vertex_count);
70
+ for (let partition = 0; partition < seed_count; partition++) {
71
+ const seed_vertex = shuffled_vertex_ids[partition];
72
+ vertex_partition[seed_vertex] = partition;
73
+ partition_weights[partition] = vertex_weights[seed_vertex];
74
+ bfs_queue[queue_tail++] = seed_vertex;
75
+ bfs_queue[queue_tail++] = partition;
76
+ }
77
+
78
+ while (queue_head < queue_tail) {
79
+ const vertex = bfs_queue[queue_head++];
80
+ const partition = bfs_queue[queue_head++];
81
+
82
+ if (partition_weights[partition] >= partition_weight_cap) {
83
+ continue;
84
+ }
85
+
86
+ const edge_start = edge_addresses[vertex];
87
+ const edge_end = edge_addresses[vertex + 1];
88
+ for (let edge_offset = edge_start; edge_offset < edge_end; edge_offset++) {
89
+ const neighbor = adjacency[edge_offset];
90
+ if (vertex_partition[neighbor] !== UNASSIGNED) {
91
+ continue;
92
+ }
93
+ vertex_partition[neighbor] = partition;
94
+ partition_weights[partition] += vertex_weights[neighbor];
95
+ bfs_queue[queue_tail++] = neighbor;
96
+ bfs_queue[queue_tail++] = partition;
97
+ if (partition_weights[partition] >= partition_weight_cap) {
98
+ break;
99
+ }
100
+ }
101
+ }
102
+
103
+ // Mop up vertices left unassigned (disconnected components, or stranded
104
+ // because every neighbour was claimed before the BFS reached them and the
105
+ // claiming partition then hit its cap). Assign each to the currently
106
+ // lightest partition.
107
+ for (let vertex = 0; vertex < vertex_count; vertex++) {
108
+ if (vertex_partition[vertex] !== UNASSIGNED) {
109
+ continue;
110
+ }
111
+ let lightest_partition = 0;
112
+ let lightest_partition_weight = partition_weights[0];
113
+ for (let partition = 1; partition < partition_count; partition++) {
114
+ if (partition_weights[partition] < lightest_partition_weight) {
115
+ lightest_partition_weight = partition_weights[partition];
116
+ lightest_partition = partition;
117
+ }
118
+ }
119
+ vertex_partition[vertex] = lightest_partition;
120
+ partition_weights[lightest_partition] += vertex_weights[vertex];
121
+ }
122
+ }