@ladybugmem/icebug 0.1.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 (624) hide show
  1. package/README.md +14 -0
  2. package/binding.gyp +54 -0
  3. package/build/Release/.deps/Release/icebug.node.d +1 -0
  4. package/build/Release/.deps/Release/obj.target/icebug/src/addon.o.d +291 -0
  5. package/build/Release/icebug.node +0 -0
  6. package/build/Release/obj.target/icebug/src/addon.o +0 -0
  7. package/lib/index.d.ts +361 -0
  8. package/lib/index.js +102 -0
  9. package/package.json +42 -0
  10. package/src/addon.cpp +1253 -0
  11. package/vendor/include/networkit/GlobalState.hpp +86 -0
  12. package/vendor/include/networkit/Globals.hpp +41 -0
  13. package/vendor/include/networkit/algebraic/AlgebraicGlobals.hpp +27 -0
  14. package/vendor/include/networkit/algebraic/CSRGeneralMatrix.hpp +1292 -0
  15. package/vendor/include/networkit/algebraic/CSRMatrix.hpp +11 -0
  16. package/vendor/include/networkit/algebraic/DenseMatrix.hpp +537 -0
  17. package/vendor/include/networkit/algebraic/DynamicMatrix.hpp +514 -0
  18. package/vendor/include/networkit/algebraic/GraphBLAS.hpp +323 -0
  19. package/vendor/include/networkit/algebraic/MatrixTools.hpp +156 -0
  20. package/vendor/include/networkit/algebraic/Semirings.hpp +171 -0
  21. package/vendor/include/networkit/algebraic/SparseAccumulator.hpp +111 -0
  22. package/vendor/include/networkit/algebraic/Vector.hpp +371 -0
  23. package/vendor/include/networkit/algebraic/algorithms/AlgebraicBFS.hpp +72 -0
  24. package/vendor/include/networkit/algebraic/algorithms/AlgebraicBellmanFord.hpp +88 -0
  25. package/vendor/include/networkit/algebraic/algorithms/AlgebraicMatchingCoarsening.hpp +96 -0
  26. package/vendor/include/networkit/algebraic/algorithms/AlgebraicPageRank.hpp +145 -0
  27. package/vendor/include/networkit/algebraic/algorithms/AlgebraicSpanningEdgeCentrality.hpp +122 -0
  28. package/vendor/include/networkit/algebraic/algorithms/AlgebraicTriangleCounting.hpp +76 -0
  29. package/vendor/include/networkit/auxiliary/AlignedAllocator.hpp +113 -0
  30. package/vendor/include/networkit/auxiliary/ArrayTools.hpp +85 -0
  31. package/vendor/include/networkit/auxiliary/BloomFilter.hpp +70 -0
  32. package/vendor/include/networkit/auxiliary/BucketPQ.hpp +142 -0
  33. package/vendor/include/networkit/auxiliary/Enforce.hpp +117 -0
  34. package/vendor/include/networkit/auxiliary/FunctionTraits.hpp +74 -0
  35. package/vendor/include/networkit/auxiliary/HashUtils.hpp +28 -0
  36. package/vendor/include/networkit/auxiliary/IncrementalUniformRandomSelector.hpp +52 -0
  37. package/vendor/include/networkit/auxiliary/Log.hpp +119 -0
  38. package/vendor/include/networkit/auxiliary/MissingMath.hpp +48 -0
  39. package/vendor/include/networkit/auxiliary/Multiprecision.hpp +17 -0
  40. package/vendor/include/networkit/auxiliary/NumberParsing.hpp +307 -0
  41. package/vendor/include/networkit/auxiliary/NumericTools.hpp +57 -0
  42. package/vendor/include/networkit/auxiliary/Parallel.hpp +56 -0
  43. package/vendor/include/networkit/auxiliary/Parallelism.hpp +33 -0
  44. package/vendor/include/networkit/auxiliary/PrioQueue.hpp +252 -0
  45. package/vendor/include/networkit/auxiliary/Random.hpp +122 -0
  46. package/vendor/include/networkit/auxiliary/SetIntersector.hpp +72 -0
  47. package/vendor/include/networkit/auxiliary/SignalHandling.hpp +39 -0
  48. package/vendor/include/networkit/auxiliary/SortedList.hpp +128 -0
  49. package/vendor/include/networkit/auxiliary/SparseVector.hpp +215 -0
  50. package/vendor/include/networkit/auxiliary/SpinLock.hpp +23 -0
  51. package/vendor/include/networkit/auxiliary/StringBuilder.hpp +322 -0
  52. package/vendor/include/networkit/auxiliary/StringTools.hpp +76 -0
  53. package/vendor/include/networkit/auxiliary/TemplateUtils.hpp +76 -0
  54. package/vendor/include/networkit/auxiliary/Timer.hpp +145 -0
  55. package/vendor/include/networkit/auxiliary/VectorComparator.hpp +32 -0
  56. package/vendor/include/networkit/base/Algorithm.hpp +41 -0
  57. package/vendor/include/networkit/base/DynAlgorithm.hpp +31 -0
  58. package/vendor/include/networkit/centrality/ApproxBetweenness.hpp +62 -0
  59. package/vendor/include/networkit/centrality/ApproxCloseness.hpp +136 -0
  60. package/vendor/include/networkit/centrality/ApproxElectricalCloseness.hpp +156 -0
  61. package/vendor/include/networkit/centrality/ApproxGroupBetweenness.hpp +124 -0
  62. package/vendor/include/networkit/centrality/ApproxSpanningEdge.hpp +84 -0
  63. package/vendor/include/networkit/centrality/Betweenness.hpp +47 -0
  64. package/vendor/include/networkit/centrality/Centrality.hpp +98 -0
  65. package/vendor/include/networkit/centrality/Closeness.hpp +107 -0
  66. package/vendor/include/networkit/centrality/ComplexPaths.hpp +113 -0
  67. package/vendor/include/networkit/centrality/CoreDecomposition.hpp +161 -0
  68. package/vendor/include/networkit/centrality/DegreeCentrality.hpp +55 -0
  69. package/vendor/include/networkit/centrality/DynApproxBetweenness.hpp +95 -0
  70. package/vendor/include/networkit/centrality/DynBetweenness.hpp +99 -0
  71. package/vendor/include/networkit/centrality/DynBetweennessOneNode.hpp +98 -0
  72. package/vendor/include/networkit/centrality/DynKatzCentrality.hpp +115 -0
  73. package/vendor/include/networkit/centrality/DynTopHarmonicCloseness.hpp +223 -0
  74. package/vendor/include/networkit/centrality/EigenvectorCentrality.hpp +41 -0
  75. package/vendor/include/networkit/centrality/EstimateBetweenness.hpp +51 -0
  76. package/vendor/include/networkit/centrality/ForestCentrality.hpp +112 -0
  77. package/vendor/include/networkit/centrality/GedWalk.hpp +225 -0
  78. package/vendor/include/networkit/centrality/GroupCloseness.hpp +115 -0
  79. package/vendor/include/networkit/centrality/GroupClosenessGrowShrink.hpp +78 -0
  80. package/vendor/include/networkit/centrality/GroupClosenessLocalSearch.hpp +77 -0
  81. package/vendor/include/networkit/centrality/GroupClosenessLocalSwaps.hpp +106 -0
  82. package/vendor/include/networkit/centrality/GroupDegree.hpp +155 -0
  83. package/vendor/include/networkit/centrality/GroupHarmonicCloseness.hpp +83 -0
  84. package/vendor/include/networkit/centrality/HarmonicCloseness.hpp +48 -0
  85. package/vendor/include/networkit/centrality/KPathCentrality.hpp +52 -0
  86. package/vendor/include/networkit/centrality/KadabraBetweenness.hpp +242 -0
  87. package/vendor/include/networkit/centrality/KatzCentrality.hpp +62 -0
  88. package/vendor/include/networkit/centrality/LaplacianCentrality.hpp +44 -0
  89. package/vendor/include/networkit/centrality/LocalClusteringCoefficient.hpp +60 -0
  90. package/vendor/include/networkit/centrality/LocalPartitionCoverage.hpp +43 -0
  91. package/vendor/include/networkit/centrality/LocalSquareClusteringCoefficient.hpp +42 -0
  92. package/vendor/include/networkit/centrality/PageRank.hpp +101 -0
  93. package/vendor/include/networkit/centrality/PermanenceCentrality.hpp +48 -0
  94. package/vendor/include/networkit/centrality/Sfigality.hpp +45 -0
  95. package/vendor/include/networkit/centrality/SpanningEdgeCentrality.hpp +86 -0
  96. package/vendor/include/networkit/centrality/TopCloseness.hpp +136 -0
  97. package/vendor/include/networkit/centrality/TopHarmonicCloseness.hpp +151 -0
  98. package/vendor/include/networkit/clique/MaximalCliques.hpp +83 -0
  99. package/vendor/include/networkit/coarsening/ClusteringProjector.hpp +59 -0
  100. package/vendor/include/networkit/coarsening/CoarsenedGraphView.hpp +156 -0
  101. package/vendor/include/networkit/coarsening/GraphCoarsening.hpp +57 -0
  102. package/vendor/include/networkit/coarsening/MatchingCoarsening.hpp +43 -0
  103. package/vendor/include/networkit/coarsening/ParallelPartitionCoarsening.hpp +33 -0
  104. package/vendor/include/networkit/coarsening/ParallelPartitionCoarseningView.hpp +62 -0
  105. package/vendor/include/networkit/community/AdjustedRandMeasure.hpp +31 -0
  106. package/vendor/include/networkit/community/ClusteringGenerator.hpp +75 -0
  107. package/vendor/include/networkit/community/CommunityDetectionAlgorithm.hpp +58 -0
  108. package/vendor/include/networkit/community/Conductance.hpp +32 -0
  109. package/vendor/include/networkit/community/CoverF1Similarity.hpp +53 -0
  110. package/vendor/include/networkit/community/CoverHubDominance.hpp +38 -0
  111. package/vendor/include/networkit/community/Coverage.hpp +25 -0
  112. package/vendor/include/networkit/community/CutClustering.hpp +62 -0
  113. package/vendor/include/networkit/community/DissimilarityMeasure.hpp +31 -0
  114. package/vendor/include/networkit/community/DynamicNMIDistance.hpp +44 -0
  115. package/vendor/include/networkit/community/EdgeCut.hpp +24 -0
  116. package/vendor/include/networkit/community/GraphClusteringTools.hpp +103 -0
  117. package/vendor/include/networkit/community/GraphStructuralRandMeasure.hpp +28 -0
  118. package/vendor/include/networkit/community/HubDominance.hpp +46 -0
  119. package/vendor/include/networkit/community/IntrapartitionDensity.hpp +44 -0
  120. package/vendor/include/networkit/community/IsolatedInterpartitionConductance.hpp +40 -0
  121. package/vendor/include/networkit/community/IsolatedInterpartitionExpansion.hpp +40 -0
  122. package/vendor/include/networkit/community/JaccardMeasure.hpp +25 -0
  123. package/vendor/include/networkit/community/LFM.hpp +49 -0
  124. package/vendor/include/networkit/community/LPDegreeOrdered.hpp +48 -0
  125. package/vendor/include/networkit/community/LocalCommunityEvaluation.hpp +100 -0
  126. package/vendor/include/networkit/community/LocalCoverEvaluation.hpp +31 -0
  127. package/vendor/include/networkit/community/LocalPartitionEvaluation.hpp +31 -0
  128. package/vendor/include/networkit/community/LouvainMapEquation.hpp +135 -0
  129. package/vendor/include/networkit/community/Modularity.hpp +54 -0
  130. package/vendor/include/networkit/community/NMIDistance.hpp +28 -0
  131. package/vendor/include/networkit/community/NodeStructuralRandMeasure.hpp +27 -0
  132. package/vendor/include/networkit/community/OverlappingCommunityDetectionAlgorithm.hpp +51 -0
  133. package/vendor/include/networkit/community/OverlappingNMIDistance.hpp +175 -0
  134. package/vendor/include/networkit/community/PLM.hpp +89 -0
  135. package/vendor/include/networkit/community/PLP.hpp +83 -0
  136. package/vendor/include/networkit/community/ParallelAgglomerativeClusterer.hpp +37 -0
  137. package/vendor/include/networkit/community/ParallelLeiden.hpp +96 -0
  138. package/vendor/include/networkit/community/ParallelLeidenView.hpp +138 -0
  139. package/vendor/include/networkit/community/PartitionFragmentation.hpp +30 -0
  140. package/vendor/include/networkit/community/PartitionHubDominance.hpp +37 -0
  141. package/vendor/include/networkit/community/PartitionIntersection.hpp +25 -0
  142. package/vendor/include/networkit/community/QualityMeasure.hpp +27 -0
  143. package/vendor/include/networkit/community/SampledGraphStructuralRandMeasure.hpp +40 -0
  144. package/vendor/include/networkit/community/SampledNodeStructuralRandMeasure.hpp +40 -0
  145. package/vendor/include/networkit/community/StablePartitionNodes.hpp +48 -0
  146. package/vendor/include/networkit/components/BiconnectedComponents.hpp +116 -0
  147. package/vendor/include/networkit/components/ComponentDecomposition.hpp +72 -0
  148. package/vendor/include/networkit/components/ConnectedComponents.hpp +55 -0
  149. package/vendor/include/networkit/components/DynConnectedComponents.hpp +71 -0
  150. package/vendor/include/networkit/components/DynWeaklyConnectedComponents.hpp +73 -0
  151. package/vendor/include/networkit/components/ParallelConnectedComponents.hpp +44 -0
  152. package/vendor/include/networkit/components/RandomSpanningForest.hpp +36 -0
  153. package/vendor/include/networkit/components/StronglyConnectedComponents.hpp +50 -0
  154. package/vendor/include/networkit/components/WeaklyConnectedComponents.hpp +59 -0
  155. package/vendor/include/networkit/correlation/Assortativity.hpp +64 -0
  156. package/vendor/include/networkit/distance/APSP.hpp +70 -0
  157. package/vendor/include/networkit/distance/AStar.hpp +68 -0
  158. package/vendor/include/networkit/distance/AStarGeneral.hpp +110 -0
  159. package/vendor/include/networkit/distance/AdamicAdarDistance.hpp +52 -0
  160. package/vendor/include/networkit/distance/AffectedNodes.hpp +130 -0
  161. package/vendor/include/networkit/distance/AlgebraicDistance.hpp +63 -0
  162. package/vendor/include/networkit/distance/BFS.hpp +43 -0
  163. package/vendor/include/networkit/distance/BidirectionalBFS.hpp +51 -0
  164. package/vendor/include/networkit/distance/BidirectionalDijkstra.hpp +69 -0
  165. package/vendor/include/networkit/distance/CommuteTimeDistance.hpp +89 -0
  166. package/vendor/include/networkit/distance/Diameter.hpp +97 -0
  167. package/vendor/include/networkit/distance/Dijkstra.hpp +50 -0
  168. package/vendor/include/networkit/distance/DynAPSP.hpp +67 -0
  169. package/vendor/include/networkit/distance/DynBFS.hpp +56 -0
  170. package/vendor/include/networkit/distance/DynDijkstra.hpp +57 -0
  171. package/vendor/include/networkit/distance/DynPrunedLandmarkLabeling.hpp +67 -0
  172. package/vendor/include/networkit/distance/DynSSSP.hpp +87 -0
  173. package/vendor/include/networkit/distance/Eccentricity.hpp +32 -0
  174. package/vendor/include/networkit/distance/EffectiveDiameter.hpp +47 -0
  175. package/vendor/include/networkit/distance/EffectiveDiameterApproximation.hpp +57 -0
  176. package/vendor/include/networkit/distance/FloydWarshall.hpp +93 -0
  177. package/vendor/include/networkit/distance/GraphDistance.hpp +49 -0
  178. package/vendor/include/networkit/distance/HopPlotApproximation.hpp +62 -0
  179. package/vendor/include/networkit/distance/IncompleteDijkstra.hpp +66 -0
  180. package/vendor/include/networkit/distance/IncompleteSSSP.hpp +41 -0
  181. package/vendor/include/networkit/distance/JaccardDistance.hpp +57 -0
  182. package/vendor/include/networkit/distance/MultiTargetBFS.hpp +32 -0
  183. package/vendor/include/networkit/distance/MultiTargetDijkstra.hpp +40 -0
  184. package/vendor/include/networkit/distance/NeighborhoodFunction.hpp +47 -0
  185. package/vendor/include/networkit/distance/NeighborhoodFunctionApproximation.hpp +56 -0
  186. package/vendor/include/networkit/distance/NeighborhoodFunctionHeuristic.hpp +56 -0
  187. package/vendor/include/networkit/distance/NodeDistance.hpp +54 -0
  188. package/vendor/include/networkit/distance/PrunedLandmarkLabeling.hpp +76 -0
  189. package/vendor/include/networkit/distance/ReverseBFS.hpp +46 -0
  190. package/vendor/include/networkit/distance/SPSP.hpp +143 -0
  191. package/vendor/include/networkit/distance/SSSP.hpp +216 -0
  192. package/vendor/include/networkit/distance/STSP.hpp +193 -0
  193. package/vendor/include/networkit/distance/Volume.hpp +66 -0
  194. package/vendor/include/networkit/dynamics/DGSStreamParser.hpp +40 -0
  195. package/vendor/include/networkit/dynamics/DGSWriter.hpp +30 -0
  196. package/vendor/include/networkit/dynamics/GraphDifference.hpp +110 -0
  197. package/vendor/include/networkit/dynamics/GraphEvent.hpp +55 -0
  198. package/vendor/include/networkit/dynamics/GraphEventHandler.hpp +39 -0
  199. package/vendor/include/networkit/dynamics/GraphEventProxy.hpp +55 -0
  200. package/vendor/include/networkit/dynamics/GraphUpdater.hpp +38 -0
  201. package/vendor/include/networkit/edgescores/ChibaNishizekiQuadrangleEdgeScore.hpp +26 -0
  202. package/vendor/include/networkit/edgescores/ChibaNishizekiTriangleEdgeScore.hpp +33 -0
  203. package/vendor/include/networkit/edgescores/EdgeScore.hpp +50 -0
  204. package/vendor/include/networkit/edgescores/EdgeScoreAsWeight.hpp +33 -0
  205. package/vendor/include/networkit/edgescores/EdgeScoreBlender.hpp +33 -0
  206. package/vendor/include/networkit/edgescores/EdgeScoreLinearizer.hpp +32 -0
  207. package/vendor/include/networkit/edgescores/EdgeScoreNormalizer.hpp +35 -0
  208. package/vendor/include/networkit/edgescores/GeometricMeanScore.hpp +29 -0
  209. package/vendor/include/networkit/edgescores/PrefixJaccardScore.hpp +23 -0
  210. package/vendor/include/networkit/edgescores/TriangleEdgeScore.hpp +39 -0
  211. package/vendor/include/networkit/embedding/Node2Vec.hpp +83 -0
  212. package/vendor/include/networkit/flow/EdmondsKarp.hpp +112 -0
  213. package/vendor/include/networkit/generators/BarabasiAlbertGenerator.hpp +87 -0
  214. package/vendor/include/networkit/generators/ChungLuGenerator.hpp +46 -0
  215. package/vendor/include/networkit/generators/ChungLuGeneratorAlamEtAl.hpp +63 -0
  216. package/vendor/include/networkit/generators/ClusteredRandomGraphGenerator.hpp +56 -0
  217. package/vendor/include/networkit/generators/ConfigurationModel.hpp +36 -0
  218. package/vendor/include/networkit/generators/DorogovtsevMendesGenerator.hpp +33 -0
  219. package/vendor/include/networkit/generators/DynamicBarabasiAlbertGenerator.hpp +33 -0
  220. package/vendor/include/networkit/generators/DynamicDGSParser.hpp +51 -0
  221. package/vendor/include/networkit/generators/DynamicDorogovtsevMendesGenerator.hpp +34 -0
  222. package/vendor/include/networkit/generators/DynamicForestFireGenerator.hpp +55 -0
  223. package/vendor/include/networkit/generators/DynamicGraphGenerator.hpp +40 -0
  224. package/vendor/include/networkit/generators/DynamicGraphSource.hpp +79 -0
  225. package/vendor/include/networkit/generators/DynamicHyperbolicGenerator.hpp +143 -0
  226. package/vendor/include/networkit/generators/DynamicPathGenerator.hpp +26 -0
  227. package/vendor/include/networkit/generators/DynamicPubWebGenerator.hpp +54 -0
  228. package/vendor/include/networkit/generators/EdgeSwitchingMarkovChainGenerator.hpp +65 -0
  229. package/vendor/include/networkit/generators/ErdosRenyiEnumerator.hpp +318 -0
  230. package/vendor/include/networkit/generators/ErdosRenyiGenerator.hpp +56 -0
  231. package/vendor/include/networkit/generators/HavelHakimiGenerator.hpp +48 -0
  232. package/vendor/include/networkit/generators/HyperbolicGenerator.hpp +236 -0
  233. package/vendor/include/networkit/generators/LFRGenerator.hpp +175 -0
  234. package/vendor/include/networkit/generators/MocnikGenerator.hpp +147 -0
  235. package/vendor/include/networkit/generators/MocnikGeneratorBasic.hpp +58 -0
  236. package/vendor/include/networkit/generators/PowerlawDegreeSequence.hpp +128 -0
  237. package/vendor/include/networkit/generators/PubWebGenerator.hpp +94 -0
  238. package/vendor/include/networkit/generators/RegularRingLatticeGenerator.hpp +37 -0
  239. package/vendor/include/networkit/generators/RmatGenerator.hpp +67 -0
  240. package/vendor/include/networkit/generators/StaticDegreeSequenceGenerator.hpp +42 -0
  241. package/vendor/include/networkit/generators/StaticGraphGenerator.hpp +30 -0
  242. package/vendor/include/networkit/generators/StochasticBlockmodel.hpp +41 -0
  243. package/vendor/include/networkit/generators/WattsStrogatzGenerator.hpp +43 -0
  244. package/vendor/include/networkit/generators/quadtree/QuadNode.hpp +857 -0
  245. package/vendor/include/networkit/generators/quadtree/QuadNodeCartesianEuclid.hpp +587 -0
  246. package/vendor/include/networkit/generators/quadtree/QuadNodePolarEuclid.hpp +726 -0
  247. package/vendor/include/networkit/generators/quadtree/Quadtree.hpp +232 -0
  248. package/vendor/include/networkit/generators/quadtree/QuadtreeCartesianEuclid.hpp +149 -0
  249. package/vendor/include/networkit/generators/quadtree/QuadtreePolarEuclid.hpp +143 -0
  250. package/vendor/include/networkit/geometric/HyperbolicSpace.hpp +248 -0
  251. package/vendor/include/networkit/geometric/Point2DWithIndex.hpp +145 -0
  252. package/vendor/include/networkit/global/ClusteringCoefficient.hpp +42 -0
  253. package/vendor/include/networkit/global/GlobalClusteringCoefficient.hpp +24 -0
  254. package/vendor/include/networkit/graph/Attributes.hpp +568 -0
  255. package/vendor/include/networkit/graph/BFS.hpp +111 -0
  256. package/vendor/include/networkit/graph/DFS.hpp +71 -0
  257. package/vendor/include/networkit/graph/Dijkstra.hpp +83 -0
  258. package/vendor/include/networkit/graph/EdgeIterators.hpp +171 -0
  259. package/vendor/include/networkit/graph/Graph.hpp +2083 -0
  260. package/vendor/include/networkit/graph/GraphBuilder.hpp +289 -0
  261. package/vendor/include/networkit/graph/GraphR.hpp +133 -0
  262. package/vendor/include/networkit/graph/GraphTools.hpp +589 -0
  263. package/vendor/include/networkit/graph/GraphW.hpp +1236 -0
  264. package/vendor/include/networkit/graph/KruskalMSF.hpp +50 -0
  265. package/vendor/include/networkit/graph/NeighborIterators.hpp +163 -0
  266. package/vendor/include/networkit/graph/NodeIterators.hpp +127 -0
  267. package/vendor/include/networkit/graph/PrimMSF.hpp +66 -0
  268. package/vendor/include/networkit/graph/RandomMaximumSpanningForest.hpp +133 -0
  269. package/vendor/include/networkit/graph/SpanningForest.hpp +41 -0
  270. package/vendor/include/networkit/graph/TopologicalSort.hpp +87 -0
  271. package/vendor/include/networkit/graph/UnionMaximumSpanningForest.hpp +126 -0
  272. package/vendor/include/networkit/graph/test/GraphBuilderBenchmark.hpp +68 -0
  273. package/vendor/include/networkit/independentset/IndependentSetFinder.hpp +44 -0
  274. package/vendor/include/networkit/independentset/Luby.hpp +27 -0
  275. package/vendor/include/networkit/io/BinaryEdgeListPartitionReader.hpp +45 -0
  276. package/vendor/include/networkit/io/BinaryEdgeListPartitionWriter.hpp +47 -0
  277. package/vendor/include/networkit/io/BinaryPartitionReader.hpp +41 -0
  278. package/vendor/include/networkit/io/BinaryPartitionWriter.hpp +44 -0
  279. package/vendor/include/networkit/io/CoverReader.hpp +27 -0
  280. package/vendor/include/networkit/io/CoverWriter.hpp +21 -0
  281. package/vendor/include/networkit/io/DGSReader.hpp +39 -0
  282. package/vendor/include/networkit/io/DibapGraphReader.hpp +43 -0
  283. package/vendor/include/networkit/io/DotGraphWriter.hpp +39 -0
  284. package/vendor/include/networkit/io/DotPartitionWriter.hpp +23 -0
  285. package/vendor/include/networkit/io/DynamicGraphReader.hpp +29 -0
  286. package/vendor/include/networkit/io/EdgeListCoverReader.hpp +35 -0
  287. package/vendor/include/networkit/io/EdgeListPartitionReader.hpp +43 -0
  288. package/vendor/include/networkit/io/EdgeListReader.hpp +61 -0
  289. package/vendor/include/networkit/io/EdgeListWriter.hpp +48 -0
  290. package/vendor/include/networkit/io/GMLGraphReader.hpp +33 -0
  291. package/vendor/include/networkit/io/GMLGraphWriter.hpp +33 -0
  292. package/vendor/include/networkit/io/GraphIO.hpp +52 -0
  293. package/vendor/include/networkit/io/GraphReader.hpp +40 -0
  294. package/vendor/include/networkit/io/GraphToolBinaryReader.hpp +71 -0
  295. package/vendor/include/networkit/io/GraphToolBinaryWriter.hpp +61 -0
  296. package/vendor/include/networkit/io/GraphWriter.hpp +27 -0
  297. package/vendor/include/networkit/io/KONECTGraphReader.hpp +44 -0
  298. package/vendor/include/networkit/io/LineFileReader.hpp +42 -0
  299. package/vendor/include/networkit/io/METISGraphReader.hpp +36 -0
  300. package/vendor/include/networkit/io/METISGraphWriter.hpp +29 -0
  301. package/vendor/include/networkit/io/METISParser.hpp +63 -0
  302. package/vendor/include/networkit/io/MTXGraphReader.hpp +31 -0
  303. package/vendor/include/networkit/io/MTXParser.hpp +87 -0
  304. package/vendor/include/networkit/io/MatrixMarketReader.hpp +33 -0
  305. package/vendor/include/networkit/io/MatrixReader.hpp +33 -0
  306. package/vendor/include/networkit/io/MemoryMappedFile.hpp +80 -0
  307. package/vendor/include/networkit/io/NetworkitBinaryGraph.hpp +144 -0
  308. package/vendor/include/networkit/io/NetworkitBinaryReader.hpp +50 -0
  309. package/vendor/include/networkit/io/NetworkitBinaryWriter.hpp +71 -0
  310. package/vendor/include/networkit/io/PartitionReader.hpp +34 -0
  311. package/vendor/include/networkit/io/PartitionWriter.hpp +31 -0
  312. package/vendor/include/networkit/io/RBGraphReader.hpp +37 -0
  313. package/vendor/include/networkit/io/RBMatrixReader.hpp +49 -0
  314. package/vendor/include/networkit/io/RasterReader.hpp +40 -0
  315. package/vendor/include/networkit/io/SNAPEdgeListPartitionReader.hpp +28 -0
  316. package/vendor/include/networkit/io/SNAPGraphReader.hpp +53 -0
  317. package/vendor/include/networkit/io/SNAPGraphWriter.hpp +53 -0
  318. package/vendor/include/networkit/io/ThrillGraphBinaryReader.hpp +44 -0
  319. package/vendor/include/networkit/io/ThrillGraphBinaryWriter.hpp +27 -0
  320. package/vendor/include/networkit/layout/LayoutAlgorithm.hpp +39 -0
  321. package/vendor/include/networkit/linkprediction/AdamicAdarIndex.hpp +37 -0
  322. package/vendor/include/networkit/linkprediction/AdjustedRandIndex.hpp +36 -0
  323. package/vendor/include/networkit/linkprediction/AlgebraicDistanceIndex.hpp +70 -0
  324. package/vendor/include/networkit/linkprediction/CommonNeighborsIndex.hpp +39 -0
  325. package/vendor/include/networkit/linkprediction/EvaluationMetric.hpp +135 -0
  326. package/vendor/include/networkit/linkprediction/JaccardIndex.hpp +44 -0
  327. package/vendor/include/networkit/linkprediction/KatzIndex.hpp +84 -0
  328. package/vendor/include/networkit/linkprediction/LinkPredictor.hpp +98 -0
  329. package/vendor/include/networkit/linkprediction/LinkThresholder.hpp +56 -0
  330. package/vendor/include/networkit/linkprediction/MissingLinksFinder.hpp +60 -0
  331. package/vendor/include/networkit/linkprediction/NeighborhoodDistanceIndex.hpp +42 -0
  332. package/vendor/include/networkit/linkprediction/NeighborhoodUtility.hpp +54 -0
  333. package/vendor/include/networkit/linkprediction/NeighborsMeasureIndex.hpp +48 -0
  334. package/vendor/include/networkit/linkprediction/PrecisionRecallMetric.hpp +40 -0
  335. package/vendor/include/networkit/linkprediction/PredictionsSorter.hpp +66 -0
  336. package/vendor/include/networkit/linkprediction/PreferentialAttachmentIndex.hpp +37 -0
  337. package/vendor/include/networkit/linkprediction/ROCMetric.hpp +39 -0
  338. package/vendor/include/networkit/linkprediction/RandomLinkSampler.hpp +47 -0
  339. package/vendor/include/networkit/linkprediction/ResourceAllocationIndex.hpp +38 -0
  340. package/vendor/include/networkit/linkprediction/SameCommunityIndex.hpp +50 -0
  341. package/vendor/include/networkit/linkprediction/TotalNeighborsIndex.hpp +39 -0
  342. package/vendor/include/networkit/linkprediction/UDegreeIndex.hpp +35 -0
  343. package/vendor/include/networkit/linkprediction/VDegreeIndex.hpp +35 -0
  344. package/vendor/include/networkit/matching/BMatcher.hpp +52 -0
  345. package/vendor/include/networkit/matching/BMatching.hpp +115 -0
  346. package/vendor/include/networkit/matching/BSuitorMatcher.hpp +170 -0
  347. package/vendor/include/networkit/matching/DynamicBSuitorMatcher.hpp +78 -0
  348. package/vendor/include/networkit/matching/LocalMaxMatcher.hpp +35 -0
  349. package/vendor/include/networkit/matching/Matcher.hpp +55 -0
  350. package/vendor/include/networkit/matching/Matching.hpp +111 -0
  351. package/vendor/include/networkit/matching/PathGrowingMatcher.hpp +46 -0
  352. package/vendor/include/networkit/matching/SuitorMatcher.hpp +62 -0
  353. package/vendor/include/networkit/numerics/ConjugateGradient.hpp +163 -0
  354. package/vendor/include/networkit/numerics/GaussSeidelRelaxation.hpp +99 -0
  355. package/vendor/include/networkit/numerics/LAMG/LAMGSettings.hpp +70 -0
  356. package/vendor/include/networkit/numerics/LAMG/Lamg.hpp +460 -0
  357. package/vendor/include/networkit/numerics/LAMG/Level/EliminationStage.hpp +47 -0
  358. package/vendor/include/networkit/numerics/LAMG/Level/Level.hpp +56 -0
  359. package/vendor/include/networkit/numerics/LAMG/Level/LevelAggregation.hpp +52 -0
  360. package/vendor/include/networkit/numerics/LAMG/Level/LevelElimination.hpp +133 -0
  361. package/vendor/include/networkit/numerics/LAMG/Level/LevelFinest.hpp +28 -0
  362. package/vendor/include/networkit/numerics/LAMG/LevelHierarchy.hpp +165 -0
  363. package/vendor/include/networkit/numerics/LAMG/MultiLevelSetup.hpp +1090 -0
  364. package/vendor/include/networkit/numerics/LAMG/SolverLamg.hpp +316 -0
  365. package/vendor/include/networkit/numerics/LinearSolver.hpp +151 -0
  366. package/vendor/include/networkit/numerics/Preconditioner/DiagonalPreconditioner.hpp +61 -0
  367. package/vendor/include/networkit/numerics/Preconditioner/IdentityPreconditioner.hpp +36 -0
  368. package/vendor/include/networkit/numerics/Smoother.hpp +37 -0
  369. package/vendor/include/networkit/overlap/HashingOverlapper.hpp +28 -0
  370. package/vendor/include/networkit/overlap/Overlapper.hpp +27 -0
  371. package/vendor/include/networkit/planarity/LeftRightPlanarityCheck.hpp +113 -0
  372. package/vendor/include/networkit/randomization/Curveball.hpp +49 -0
  373. package/vendor/include/networkit/randomization/CurveballGlobalTradeGenerator.hpp +39 -0
  374. package/vendor/include/networkit/randomization/CurveballUniformTradeGenerator.hpp +39 -0
  375. package/vendor/include/networkit/randomization/DegreePreservingShuffle.hpp +82 -0
  376. package/vendor/include/networkit/randomization/EdgeSwitching.hpp +157 -0
  377. package/vendor/include/networkit/randomization/GlobalCurveball.hpp +69 -0
  378. package/vendor/include/networkit/randomization/GlobalTradeSequence.hpp +303 -0
  379. package/vendor/include/networkit/reachability/AllSimplePaths.hpp +122 -0
  380. package/vendor/include/networkit/reachability/ReachableNodes.hpp +83 -0
  381. package/vendor/include/networkit/scd/ApproximatePageRank.hpp +51 -0
  382. package/vendor/include/networkit/scd/CliqueDetect.hpp +55 -0
  383. package/vendor/include/networkit/scd/CombinedSCD.hpp +51 -0
  384. package/vendor/include/networkit/scd/GCE.hpp +42 -0
  385. package/vendor/include/networkit/scd/LFMLocal.hpp +54 -0
  386. package/vendor/include/networkit/scd/LocalT.hpp +40 -0
  387. package/vendor/include/networkit/scd/LocalTightnessExpansion.hpp +46 -0
  388. package/vendor/include/networkit/scd/PageRankNibble.hpp +55 -0
  389. package/vendor/include/networkit/scd/RandomBFS.hpp +33 -0
  390. package/vendor/include/networkit/scd/SCDGroundTruthComparison.hpp +121 -0
  391. package/vendor/include/networkit/scd/SelectiveCommunityDetector.hpp +76 -0
  392. package/vendor/include/networkit/scd/SetConductance.hpp +47 -0
  393. package/vendor/include/networkit/scd/TCE.hpp +41 -0
  394. package/vendor/include/networkit/scd/TwoPhaseL.hpp +40 -0
  395. package/vendor/include/networkit/scoring/EdgeScoring.hpp +44 -0
  396. package/vendor/include/networkit/scoring/ModularityScoring.hpp +79 -0
  397. package/vendor/include/networkit/simulation/EpidemicSimulationSEIR.hpp +59 -0
  398. package/vendor/include/networkit/sparsification/ChanceCorrectedTriangleScore.hpp +28 -0
  399. package/vendor/include/networkit/sparsification/ForestFireScore.hpp +34 -0
  400. package/vendor/include/networkit/sparsification/GlobalThresholdFilter.hpp +40 -0
  401. package/vendor/include/networkit/sparsification/LocalDegreeScore.hpp +30 -0
  402. package/vendor/include/networkit/sparsification/LocalFilterScore.hpp +124 -0
  403. package/vendor/include/networkit/sparsification/LocalSimilarityScore.hpp +63 -0
  404. package/vendor/include/networkit/sparsification/MultiscaleScore.hpp +38 -0
  405. package/vendor/include/networkit/sparsification/RandomEdgeScore.hpp +33 -0
  406. package/vendor/include/networkit/sparsification/RandomNodeEdgeScore.hpp +29 -0
  407. package/vendor/include/networkit/sparsification/SCANStructuralSimilarityScore.hpp +23 -0
  408. package/vendor/include/networkit/sparsification/SimmelianOverlapScore.hpp +35 -0
  409. package/vendor/include/networkit/sparsification/SimmelianScore.hpp +92 -0
  410. package/vendor/include/networkit/sparsification/Sparsifiers.hpp +166 -0
  411. package/vendor/include/networkit/structures/Cover.hpp +248 -0
  412. package/vendor/include/networkit/structures/LocalCommunity.hpp +363 -0
  413. package/vendor/include/networkit/structures/Partition.hpp +335 -0
  414. package/vendor/include/networkit/structures/UnionFind.hpp +66 -0
  415. package/vendor/include/networkit/viz/GraphLayoutAlgorithm.hpp +157 -0
  416. package/vendor/include/networkit/viz/MaxentStress.hpp +346 -0
  417. package/vendor/include/networkit/viz/Octree.hpp +428 -0
  418. package/vendor/include/networkit/viz/PivotMDS.hpp +63 -0
  419. package/vendor/include/networkit/viz/Point.hpp +415 -0
  420. package/vendor/include/networkit/viz/PostscriptWriter.hpp +78 -0
  421. package/vendor/include/tlx/algorithm/exclusive_scan.hpp +56 -0
  422. package/vendor/include/tlx/algorithm/is_sorted_cmp.hpp +56 -0
  423. package/vendor/include/tlx/algorithm/merge_advance.hpp +177 -0
  424. package/vendor/include/tlx/algorithm/merge_combine.hpp +76 -0
  425. package/vendor/include/tlx/algorithm/multisequence_partition.hpp +346 -0
  426. package/vendor/include/tlx/algorithm/multisequence_selection.hpp +351 -0
  427. package/vendor/include/tlx/algorithm/multiway_merge.hpp +1385 -0
  428. package/vendor/include/tlx/algorithm/multiway_merge_splitting.hpp +257 -0
  429. package/vendor/include/tlx/algorithm/parallel_multiway_merge.hpp +408 -0
  430. package/vendor/include/tlx/algorithm/random_bipartition_shuffle.hpp +116 -0
  431. package/vendor/include/tlx/algorithm.hpp +36 -0
  432. package/vendor/include/tlx/allocator_base.hpp +100 -0
  433. package/vendor/include/tlx/backtrace.hpp +54 -0
  434. package/vendor/include/tlx/cmdline_parser.hpp +498 -0
  435. package/vendor/include/tlx/container/btree.hpp +3977 -0
  436. package/vendor/include/tlx/container/btree_map.hpp +634 -0
  437. package/vendor/include/tlx/container/btree_multimap.hpp +627 -0
  438. package/vendor/include/tlx/container/btree_multiset.hpp +612 -0
  439. package/vendor/include/tlx/container/btree_set.hpp +612 -0
  440. package/vendor/include/tlx/container/d_ary_addressable_int_heap.hpp +416 -0
  441. package/vendor/include/tlx/container/d_ary_heap.hpp +311 -0
  442. package/vendor/include/tlx/container/loser_tree.hpp +1009 -0
  443. package/vendor/include/tlx/container/lru_cache.hpp +319 -0
  444. package/vendor/include/tlx/container/radix_heap.hpp +735 -0
  445. package/vendor/include/tlx/container/ring_buffer.hpp +428 -0
  446. package/vendor/include/tlx/container/simple_vector.hpp +304 -0
  447. package/vendor/include/tlx/container/splay_tree.hpp +399 -0
  448. package/vendor/include/tlx/container/string_view.hpp +805 -0
  449. package/vendor/include/tlx/container.hpp +40 -0
  450. package/vendor/include/tlx/counting_ptr.hpp +522 -0
  451. package/vendor/include/tlx/define/attribute_always_inline.hpp +34 -0
  452. package/vendor/include/tlx/define/attribute_fallthrough.hpp +36 -0
  453. package/vendor/include/tlx/define/attribute_format_printf.hpp +34 -0
  454. package/vendor/include/tlx/define/attribute_packed.hpp +34 -0
  455. package/vendor/include/tlx/define/attribute_warn_unused_result.hpp +34 -0
  456. package/vendor/include/tlx/define/constexpr.hpp +31 -0
  457. package/vendor/include/tlx/define/deprecated.hpp +39 -0
  458. package/vendor/include/tlx/define/endian.hpp +49 -0
  459. package/vendor/include/tlx/define/likely.hpp +33 -0
  460. package/vendor/include/tlx/define/visibility_hidden.hpp +34 -0
  461. package/vendor/include/tlx/define.hpp +36 -0
  462. package/vendor/include/tlx/delegate.hpp +524 -0
  463. package/vendor/include/tlx/die/core.hpp +311 -0
  464. package/vendor/include/tlx/die.hpp +106 -0
  465. package/vendor/include/tlx/digest/md5.hpp +81 -0
  466. package/vendor/include/tlx/digest/sha1.hpp +81 -0
  467. package/vendor/include/tlx/digest/sha256.hpp +81 -0
  468. package/vendor/include/tlx/digest/sha512.hpp +81 -0
  469. package/vendor/include/tlx/digest.hpp +30 -0
  470. package/vendor/include/tlx/logger/all.hpp +33 -0
  471. package/vendor/include/tlx/logger/array.hpp +43 -0
  472. package/vendor/include/tlx/logger/core.hpp +287 -0
  473. package/vendor/include/tlx/logger/deque.hpp +42 -0
  474. package/vendor/include/tlx/logger/map.hpp +65 -0
  475. package/vendor/include/tlx/logger/set.hpp +60 -0
  476. package/vendor/include/tlx/logger/tuple.hpp +66 -0
  477. package/vendor/include/tlx/logger/unordered_map.hpp +68 -0
  478. package/vendor/include/tlx/logger/unordered_set.hpp +64 -0
  479. package/vendor/include/tlx/logger/wrap_unprintable.hpp +75 -0
  480. package/vendor/include/tlx/logger.hpp +44 -0
  481. package/vendor/include/tlx/math/abs_diff.hpp +35 -0
  482. package/vendor/include/tlx/math/aggregate.hpp +231 -0
  483. package/vendor/include/tlx/math/aggregate_min_max.hpp +116 -0
  484. package/vendor/include/tlx/math/bswap.hpp +148 -0
  485. package/vendor/include/tlx/math/bswap_be.hpp +79 -0
  486. package/vendor/include/tlx/math/bswap_le.hpp +79 -0
  487. package/vendor/include/tlx/math/clz.hpp +174 -0
  488. package/vendor/include/tlx/math/ctz.hpp +174 -0
  489. package/vendor/include/tlx/math/div_ceil.hpp +36 -0
  490. package/vendor/include/tlx/math/ffs.hpp +123 -0
  491. package/vendor/include/tlx/math/integer_log2.hpp +189 -0
  492. package/vendor/include/tlx/math/is_power_of_two.hpp +74 -0
  493. package/vendor/include/tlx/math/polynomial_regression.hpp +243 -0
  494. package/vendor/include/tlx/math/popcount.hpp +173 -0
  495. package/vendor/include/tlx/math/power_to_the.hpp +44 -0
  496. package/vendor/include/tlx/math/rol.hpp +112 -0
  497. package/vendor/include/tlx/math/ror.hpp +112 -0
  498. package/vendor/include/tlx/math/round_to_power_of_two.hpp +121 -0
  499. package/vendor/include/tlx/math/round_up.hpp +36 -0
  500. package/vendor/include/tlx/math/sgn.hpp +38 -0
  501. package/vendor/include/tlx/math.hpp +46 -0
  502. package/vendor/include/tlx/meta/apply_tuple.hpp +55 -0
  503. package/vendor/include/tlx/meta/call_for_range.hpp +78 -0
  504. package/vendor/include/tlx/meta/call_foreach.hpp +60 -0
  505. package/vendor/include/tlx/meta/call_foreach_tuple.hpp +60 -0
  506. package/vendor/include/tlx/meta/call_foreach_tuple_with_index.hpp +61 -0
  507. package/vendor/include/tlx/meta/call_foreach_with_index.hpp +64 -0
  508. package/vendor/include/tlx/meta/enable_if.hpp +37 -0
  509. package/vendor/include/tlx/meta/fold_left.hpp +63 -0
  510. package/vendor/include/tlx/meta/fold_left_tuple.hpp +60 -0
  511. package/vendor/include/tlx/meta/fold_right.hpp +63 -0
  512. package/vendor/include/tlx/meta/fold_right_tuple.hpp +60 -0
  513. package/vendor/include/tlx/meta/function_chain.hpp +197 -0
  514. package/vendor/include/tlx/meta/function_stack.hpp +189 -0
  515. package/vendor/include/tlx/meta/has_member.hpp +80 -0
  516. package/vendor/include/tlx/meta/has_method.hpp +117 -0
  517. package/vendor/include/tlx/meta/index_sequence.hpp +66 -0
  518. package/vendor/include/tlx/meta/is_std_array.hpp +40 -0
  519. package/vendor/include/tlx/meta/is_std_pair.hpp +39 -0
  520. package/vendor/include/tlx/meta/is_std_tuple.hpp +39 -0
  521. package/vendor/include/tlx/meta/is_std_vector.hpp +39 -0
  522. package/vendor/include/tlx/meta/log2.hpp +101 -0
  523. package/vendor/include/tlx/meta/no_operation.hpp +55 -0
  524. package/vendor/include/tlx/meta/static_index.hpp +42 -0
  525. package/vendor/include/tlx/meta/vexpand.hpp +34 -0
  526. package/vendor/include/tlx/meta/vmap_for_range.hpp +84 -0
  527. package/vendor/include/tlx/meta/vmap_foreach.hpp +63 -0
  528. package/vendor/include/tlx/meta/vmap_foreach_tuple.hpp +59 -0
  529. package/vendor/include/tlx/meta/vmap_foreach_tuple_with_index.hpp +62 -0
  530. package/vendor/include/tlx/meta/vmap_foreach_with_index.hpp +70 -0
  531. package/vendor/include/tlx/meta.hpp +55 -0
  532. package/vendor/include/tlx/multi_timer.hpp +148 -0
  533. package/vendor/include/tlx/port/setenv.hpp +31 -0
  534. package/vendor/include/tlx/port.hpp +27 -0
  535. package/vendor/include/tlx/semaphore.hpp +119 -0
  536. package/vendor/include/tlx/simple_vector.hpp +20 -0
  537. package/vendor/include/tlx/siphash.hpp +282 -0
  538. package/vendor/include/tlx/sort/networks/best.hpp +611 -0
  539. package/vendor/include/tlx/sort/networks/bose_nelson.hpp +412 -0
  540. package/vendor/include/tlx/sort/networks/bose_nelson_parameter.hpp +507 -0
  541. package/vendor/include/tlx/sort/networks/cswap.hpp +60 -0
  542. package/vendor/include/tlx/sort/parallel_mergesort.hpp +398 -0
  543. package/vendor/include/tlx/sort/strings/insertion_sort.hpp +232 -0
  544. package/vendor/include/tlx/sort/strings/multikey_quicksort.hpp +185 -0
  545. package/vendor/include/tlx/sort/strings/parallel_sample_sort.hpp +1647 -0
  546. package/vendor/include/tlx/sort/strings/radix_sort.hpp +934 -0
  547. package/vendor/include/tlx/sort/strings/sample_sort_tools.hpp +756 -0
  548. package/vendor/include/tlx/sort/strings/string_ptr.hpp +426 -0
  549. package/vendor/include/tlx/sort/strings/string_set.hpp +800 -0
  550. package/vendor/include/tlx/sort/strings.hpp +329 -0
  551. package/vendor/include/tlx/sort/strings_parallel.hpp +325 -0
  552. package/vendor/include/tlx/sort.hpp +29 -0
  553. package/vendor/include/tlx/stack_allocator.hpp +226 -0
  554. package/vendor/include/tlx/string/appendline.hpp +35 -0
  555. package/vendor/include/tlx/string/base64.hpp +87 -0
  556. package/vendor/include/tlx/string/bitdump.hpp +139 -0
  557. package/vendor/include/tlx/string/compare_icase.hpp +42 -0
  558. package/vendor/include/tlx/string/contains.hpp +36 -0
  559. package/vendor/include/tlx/string/contains_word.hpp +42 -0
  560. package/vendor/include/tlx/string/ends_with.hpp +79 -0
  561. package/vendor/include/tlx/string/equal_icase.hpp +42 -0
  562. package/vendor/include/tlx/string/erase_all.hpp +70 -0
  563. package/vendor/include/tlx/string/escape_html.hpp +34 -0
  564. package/vendor/include/tlx/string/escape_uri.hpp +34 -0
  565. package/vendor/include/tlx/string/expand_environment_variables.hpp +49 -0
  566. package/vendor/include/tlx/string/extract_between.hpp +40 -0
  567. package/vendor/include/tlx/string/format_iec_units.hpp +32 -0
  568. package/vendor/include/tlx/string/format_si_iec_units.hpp +19 -0
  569. package/vendor/include/tlx/string/format_si_units.hpp +32 -0
  570. package/vendor/include/tlx/string/hash_djb2.hpp +87 -0
  571. package/vendor/include/tlx/string/hash_sdbm.hpp +86 -0
  572. package/vendor/include/tlx/string/hexdump.hpp +154 -0
  573. package/vendor/include/tlx/string/index_of.hpp +56 -0
  574. package/vendor/include/tlx/string/join.hpp +65 -0
  575. package/vendor/include/tlx/string/join_generic.hpp +89 -0
  576. package/vendor/include/tlx/string/join_quoted.hpp +46 -0
  577. package/vendor/include/tlx/string/less_icase.hpp +64 -0
  578. package/vendor/include/tlx/string/levenshtein.hpp +193 -0
  579. package/vendor/include/tlx/string/pad.hpp +39 -0
  580. package/vendor/include/tlx/string/parse_si_iec_units.hpp +46 -0
  581. package/vendor/include/tlx/string/parse_uri.hpp +66 -0
  582. package/vendor/include/tlx/string/parse_uri_form_data.hpp +136 -0
  583. package/vendor/include/tlx/string/replace.hpp +141 -0
  584. package/vendor/include/tlx/string/split.hpp +170 -0
  585. package/vendor/include/tlx/string/split_quoted.hpp +49 -0
  586. package/vendor/include/tlx/string/split_view.hpp +218 -0
  587. package/vendor/include/tlx/string/split_words.hpp +53 -0
  588. package/vendor/include/tlx/string/ssprintf.hpp +45 -0
  589. package/vendor/include/tlx/string/ssprintf_generic.hpp +95 -0
  590. package/vendor/include/tlx/string/starts_with.hpp +44 -0
  591. package/vendor/include/tlx/string/to_lower.hpp +47 -0
  592. package/vendor/include/tlx/string/to_upper.hpp +47 -0
  593. package/vendor/include/tlx/string/trim.hpp +298 -0
  594. package/vendor/include/tlx/string/union_words.hpp +33 -0
  595. package/vendor/include/tlx/string/word_wrap.hpp +35 -0
  596. package/vendor/include/tlx/string.hpp +68 -0
  597. package/vendor/include/tlx/thread_barrier_mutex.hpp +109 -0
  598. package/vendor/include/tlx/thread_barrier_spin.hpp +127 -0
  599. package/vendor/include/tlx/thread_pool.hpp +151 -0
  600. package/vendor/include/tlx/timestamp.hpp +23 -0
  601. package/vendor/include/tlx/unused.hpp +28 -0
  602. package/vendor/include/tlx/vector_free.hpp +30 -0
  603. package/vendor/include/tlx/version.hpp +49 -0
  604. package/vendor/include/ttmath/ttmath.h +2881 -0
  605. package/vendor/include/ttmath/ttmathbig.h +6111 -0
  606. package/vendor/include/ttmath/ttmathdec.h +419 -0
  607. package/vendor/include/ttmath/ttmathint.h +1923 -0
  608. package/vendor/include/ttmath/ttmathmisc.h +250 -0
  609. package/vendor/include/ttmath/ttmathobjects.h +812 -0
  610. package/vendor/include/ttmath/ttmathparser.h +2791 -0
  611. package/vendor/include/ttmath/ttmaththreads.h +252 -0
  612. package/vendor/include/ttmath/ttmathtypes.h +707 -0
  613. package/vendor/include/ttmath/ttmathuint.h +4190 -0
  614. package/vendor/include/ttmath/ttmathuint_noasm.h +1038 -0
  615. package/vendor/include/ttmath/ttmathuint_x86.h +1620 -0
  616. package/vendor/include/ttmath/ttmathuint_x86_64.h +1177 -0
  617. package/vendor/lib/cmake/tlx/tlx-config.cmake +51 -0
  618. package/vendor/lib/cmake/tlx/tlx-targets-release.cmake +19 -0
  619. package/vendor/lib/cmake/tlx/tlx-targets.cmake +106 -0
  620. package/vendor/lib/cmake/tlx/tlx-version.cmake +11 -0
  621. package/vendor/lib/libnetworkit.dylib +0 -0
  622. package/vendor/lib/libtlx.a +0 -0
  623. package/vendor/lib/pkgconfig/networkit.pc +11 -0
  624. package/vendor/lib/pkgconfig/tlx.pc +11 -0
@@ -0,0 +1,3977 @@
1
+ /*******************************************************************************
2
+ * tlx/container/btree.hpp
3
+ *
4
+ * Part of tlx - http://panthema.net/tlx
5
+ *
6
+ * Copyright (C) 2008-2017 Timo Bingmann <tb@panthema.net>
7
+ *
8
+ * All rights reserved. Published under the Boost Software License, Version 1.0
9
+ ******************************************************************************/
10
+
11
+ #ifndef TLX_CONTAINER_BTREE_HEADER
12
+ #define TLX_CONTAINER_BTREE_HEADER
13
+
14
+ #include <tlx/die/core.hpp>
15
+
16
+ // *** Required Headers from the STL
17
+
18
+ #include <algorithm>
19
+ #include <cassert>
20
+ #include <cstddef>
21
+ #include <functional>
22
+ #include <iterator>
23
+ #include <memory>
24
+ #include <utility>
25
+
26
+ namespace tlx {
27
+
28
+ //! \addtogroup tlx_container
29
+ //! \{
30
+ //! \defgroup tlx_container_btree B+ Trees
31
+ //! B+ tree variants
32
+ //! \{
33
+
34
+ // *** Debugging Macros
35
+
36
+ #ifdef TLX_BTREE_DEBUG
37
+
38
+ #include <iostream>
39
+
40
+ //! Print out debug information to std::cout if TLX_BTREE_DEBUG is defined.
41
+ #define TLX_BTREE_PRINT(x) \
42
+ do \
43
+ { \
44
+ if (debug) \
45
+ (std::cout << x << std::endl); \
46
+ } while (0)
47
+
48
+ //! Assertion only if TLX_BTREE_DEBUG is defined. This is not used in verify().
49
+ #define TLX_BTREE_ASSERT(x) \
50
+ do \
51
+ { \
52
+ assert(x); \
53
+ } while (0)
54
+
55
+ #else
56
+
57
+ //! Print out debug information to std::cout if TLX_BTREE_DEBUG is defined.
58
+ #define TLX_BTREE_PRINT(x) \
59
+ do \
60
+ { \
61
+ } while (0)
62
+
63
+ //! Assertion only if TLX_BTREE_DEBUG is defined. This is not used in verify().
64
+ #define TLX_BTREE_ASSERT(x) \
65
+ do \
66
+ { \
67
+ } while (0)
68
+
69
+ #endif
70
+
71
+ //! The maximum of a and b. Used in some compile-time formulas.
72
+ #define TLX_BTREE_MAX(a, b) ((a) < (b) ? (b) : (a))
73
+
74
+ #ifndef TLX_BTREE_FRIENDS
75
+ //! The macro TLX_BTREE_FRIENDS can be used by outside class to access the B+
76
+ //! tree internals. This was added for wxBTreeDemo to be able to draw the
77
+ //! tree.
78
+ #define TLX_BTREE_FRIENDS friend class btree_friend
79
+ #endif
80
+
81
+ /*!
82
+ * Generates default traits for a B+ tree used as a set or map. It estimates
83
+ * leaf and inner node sizes by assuming a cache line multiple of 256 bytes.
84
+ */
85
+ template <typename Key, typename Value>
86
+ struct btree_default_traits
87
+ {
88
+ //! If true, the tree will self verify its invariants after each insert() or
89
+ //! erase(). The header must have been compiled with TLX_BTREE_DEBUG
90
+ //! defined.
91
+ static const bool self_verify = false;
92
+
93
+ //! If true, the tree will print out debug information and a tree dump
94
+ //! during insert() or erase() operation. The header must have been
95
+ //! compiled with TLX_BTREE_DEBUG defined and key_type must be std::ostream
96
+ //! printable.
97
+ static const bool debug = false;
98
+
99
+ //! Number of slots in each leaf of the tree. Estimated so that each node
100
+ //! has a size of about 256 bytes.
101
+ static const int leaf_slots = TLX_BTREE_MAX(8, 256 / (sizeof(Value)));
102
+
103
+ //! Number of slots in each inner node of the tree. Estimated so that each
104
+ //! node has a size of about 256 bytes.
105
+ static const int inner_slots =
106
+ TLX_BTREE_MAX(8, 256 / (sizeof(Key) + sizeof(void*)));
107
+
108
+ //! As of stx-btree-0.9, the code does linear search in find_lower() and
109
+ //! find_upper() instead of binary_search, unless the node size is larger
110
+ //! than this threshold. See notes at
111
+ //! http://panthema.net/2013/0504-STX-B+Tree-Binary-vs-Linear-Search
112
+ static const size_t binsearch_threshold = 256;
113
+ };
114
+
115
+ /*!
116
+ * Basic class implementing a B+ tree data structure in memory.
117
+ *
118
+ * The base implementation of an in-memory B+ tree. It is based on the
119
+ * implementation in Cormen's Introduction into Algorithms, Jan Jannink's paper
120
+ * and other algorithm resources. Almost all STL-required function calls are
121
+ * implemented. The asymptotic time requirements of the STL are not always
122
+ * fulfilled in theory, however, in practice this B+ tree performs better than a
123
+ * red-black tree and almost always uses less memory. The insertion function
124
+ * splits the nodes on the recursion unroll. Erase is largely based on Jannink's
125
+ * ideas.
126
+ *
127
+ * This class is specialized into btree_set, btree_multiset, btree_map and
128
+ * btree_multimap using default template parameters and facade functions.
129
+ */
130
+ template <typename Key, typename Value, typename KeyOfValue,
131
+ typename Compare = std::less<Key>,
132
+ typename Traits = btree_default_traits<Key, Value>,
133
+ bool Duplicates = false, typename Allocator = std::allocator<Value> >
134
+ class BTree
135
+ {
136
+ public:
137
+ //! \name Template Parameter Types
138
+ //! \{
139
+
140
+ //! First template parameter: The key type of the B+ tree. This is stored in
141
+ //! inner nodes.
142
+ typedef Key key_type;
143
+
144
+ //! Second template parameter: Composition pair of key and data types, or
145
+ //! just the key for set containers. This data type is stored in the leaves.
146
+ typedef Value value_type;
147
+
148
+ //! Third template: key extractor class to pull key_type from value_type.
149
+ typedef KeyOfValue key_of_value;
150
+
151
+ //! Fourth template parameter: key_type comparison function object
152
+ typedef Compare key_compare;
153
+
154
+ //! Fifth template parameter: Traits object used to define more parameters
155
+ //! of the B+ tree
156
+ typedef Traits traits;
157
+
158
+ //! Sixth template parameter: Allow duplicate keys in the B+ tree. Used to
159
+ //! implement multiset and multimap.
160
+ static const bool allow_duplicates = Duplicates;
161
+
162
+ //! Seventh template parameter: STL allocator for tree nodes
163
+ typedef Allocator allocator_type;
164
+
165
+ //! \}
166
+
167
+ // The macro TLX_BTREE_FRIENDS can be used by outside class to access the B+
168
+ // tree internals. This was added for wxBTreeDemo to be able to draw the
169
+ // tree.
170
+ TLX_BTREE_FRIENDS;
171
+
172
+ public:
173
+ //! \name Constructed Types
174
+ //! \{
175
+
176
+ //! Typedef of our own type
177
+ typedef BTree<key_type, value_type, key_of_value, key_compare, traits,
178
+ allow_duplicates, allocator_type>
179
+ Self;
180
+
181
+ //! Size type used to count keys
182
+ typedef size_t size_type;
183
+
184
+ //! \}
185
+
186
+ public:
187
+ //! \name Static Constant Options and Values of the B+ Tree
188
+ //! \{
189
+
190
+ //! Base B+ tree parameter: The number of key/data slots in each leaf
191
+ static const unsigned short leaf_slotmax = traits::leaf_slots;
192
+
193
+ //! Base B+ tree parameter: The number of key slots in each inner node,
194
+ //! this can differ from slots in each leaf.
195
+ static const unsigned short inner_slotmax = traits::inner_slots;
196
+
197
+ //! Computed B+ tree parameter: The minimum number of key/data slots used
198
+ //! in a leaf. If fewer slots are used, the leaf will be merged or slots
199
+ //! shifted from it's siblings.
200
+ static const unsigned short leaf_slotmin = (leaf_slotmax / 2);
201
+
202
+ //! Computed B+ tree parameter: The minimum number of key slots used
203
+ //! in an inner node. If fewer slots are used, the inner node will be
204
+ //! merged or slots shifted from it's siblings.
205
+ static const unsigned short inner_slotmin = (inner_slotmax / 2);
206
+
207
+ //! Debug parameter: Enables expensive and thorough checking of the B+ tree
208
+ //! invariants after each insert/erase operation.
209
+ static const bool self_verify = traits::self_verify;
210
+
211
+ //! Debug parameter: Prints out lots of debug information about how the
212
+ //! algorithms change the tree. Requires the header file to be compiled
213
+ //! with TLX_BTREE_DEBUG and the key type must be std::ostream printable.
214
+ static const bool debug = traits::debug;
215
+
216
+ //! \}
217
+
218
+ private:
219
+ //! \name Node Classes for In-Memory Nodes
220
+ //! \{
221
+
222
+ //! The header structure of each node in-memory. This structure is extended
223
+ //! by InnerNode or LeafNode.
224
+ struct node
225
+ {
226
+ //! Level in the b-tree, if level == 0 -> leaf node
227
+ unsigned short level;
228
+
229
+ //! Number of key slotuse use, so the number of valid children or data
230
+ //! pointers
231
+ unsigned short slotuse;
232
+
233
+ //! Delayed initialisation of constructed node.
234
+ void initialize(const unsigned short l)
235
+ {
236
+ level = l;
237
+ slotuse = 0;
238
+ }
239
+
240
+ //! True if this is a leaf node.
241
+ bool is_leafnode() const
242
+ {
243
+ return (level == 0);
244
+ }
245
+ };
246
+
247
+ //! Extended structure of a inner node in-memory. Contains only keys and no
248
+ //! data items.
249
+ struct InnerNode : public node
250
+ {
251
+ //! Define an related allocator for the InnerNode structs.
252
+ typedef typename std::allocator_traits<
253
+ Allocator>::template rebind_alloc<InnerNode>
254
+ alloc_type;
255
+
256
+ //! Keys of children or data pointers
257
+ key_type slotkey[inner_slotmax];
258
+
259
+ //! Pointers to children
260
+ node* childid[inner_slotmax + 1];
261
+
262
+ //! Set variables to initial values.
263
+ void initialize(const unsigned short l)
264
+ {
265
+ node::initialize(l);
266
+ }
267
+
268
+ //! Return key in slot s
269
+ const key_type& key(size_t s) const
270
+ {
271
+ return slotkey[s];
272
+ }
273
+
274
+ //! True if the node's slots are full.
275
+ bool is_full() const
276
+ {
277
+ return (node::slotuse == inner_slotmax);
278
+ }
279
+
280
+ //! True if few used entries, less than half full.
281
+ bool is_few() const
282
+ {
283
+ return (node::slotuse <= inner_slotmin);
284
+ }
285
+
286
+ //! True if node has too few entries.
287
+ bool is_underflow() const
288
+ {
289
+ return (node::slotuse < inner_slotmin);
290
+ }
291
+ };
292
+
293
+ //! Extended structure of a leaf node in memory. Contains pairs of keys and
294
+ //! data items. Key and data slots are kept together in value_type.
295
+ struct LeafNode : public node
296
+ {
297
+ //! Define an related allocator for the LeafNode structs.
298
+ typedef typename std::allocator_traits<
299
+ Allocator>::template rebind_alloc<LeafNode>
300
+ alloc_type;
301
+
302
+ //! Double linked list pointers to traverse the leaves
303
+ LeafNode* prev_leaf;
304
+
305
+ //! Double linked list pointers to traverse the leaves
306
+ LeafNode* next_leaf;
307
+
308
+ //! Array of (key, data) pairs
309
+ value_type slotdata[leaf_slotmax];
310
+
311
+ //! Set variables to initial values
312
+ void initialize()
313
+ {
314
+ node::initialize(0);
315
+ prev_leaf = next_leaf = nullptr;
316
+ }
317
+
318
+ //! Return key in slot s.
319
+ const key_type& key(size_t s) const
320
+ {
321
+ return key_of_value::get(slotdata[s]);
322
+ }
323
+
324
+ //! True if the node's slots are full.
325
+ bool is_full() const
326
+ {
327
+ return (node::slotuse == leaf_slotmax);
328
+ }
329
+
330
+ //! True if few used entries, less than half full.
331
+ bool is_few() const
332
+ {
333
+ return (node::slotuse <= leaf_slotmin);
334
+ }
335
+
336
+ //! True if node has too few entries.
337
+ bool is_underflow() const
338
+ {
339
+ return (node::slotuse < leaf_slotmin);
340
+ }
341
+
342
+ //! Set the (key,data) pair in slot. Overloaded function used by
343
+ //! bulk_load().
344
+ void set_slot(unsigned short slot, const value_type& value)
345
+ {
346
+ TLX_BTREE_ASSERT(slot < node::slotuse);
347
+ slotdata[slot] = value;
348
+ }
349
+ };
350
+
351
+ //! \}
352
+
353
+ public:
354
+ //! \name Iterators and Reverse Iterators
355
+ //! \{
356
+
357
+ class iterator;
358
+ class const_iterator;
359
+ class reverse_iterator;
360
+ class const_reverse_iterator;
361
+
362
+ //! STL-like iterator object for B+ tree items. The iterator points to a
363
+ //! specific slot number in a leaf.
364
+ class iterator
365
+ {
366
+ public:
367
+ // *** Types
368
+
369
+ //! The key type of the btree. Returned by key().
370
+ typedef typename BTree::key_type key_type;
371
+
372
+ //! The value type of the btree. Returned by operator*().
373
+ typedef typename BTree::value_type value_type;
374
+
375
+ //! Reference to the value_type. STL required.
376
+ typedef value_type& reference;
377
+
378
+ //! Pointer to the value_type. STL required.
379
+ typedef value_type* pointer;
380
+
381
+ //! STL-magic iterator category
382
+ typedef std::bidirectional_iterator_tag iterator_category;
383
+
384
+ //! STL-magic
385
+ typedef ptrdiff_t difference_type;
386
+
387
+ //! Our own type
388
+ typedef iterator self;
389
+
390
+ private:
391
+ // *** Members
392
+
393
+ //! The currently referenced leaf node of the tree
394
+ typename BTree::LeafNode* curr_leaf;
395
+
396
+ //! Current key/data slot referenced
397
+ unsigned short curr_slot;
398
+
399
+ //! Friendly to the const_iterator, so it may access the two data items
400
+ //! directly.
401
+ friend class const_iterator;
402
+
403
+ //! Also friendly to the reverse_iterator, so it may access the two
404
+ //! data items directly.
405
+ friend class reverse_iterator;
406
+
407
+ //! Also friendly to the const_reverse_iterator, so it may access the
408
+ //! two data items directly.
409
+ friend class const_reverse_iterator;
410
+
411
+ //! Also friendly to the base btree class, because erase_iter() needs
412
+ //! to read the curr_leaf and curr_slot values directly.
413
+ friend class BTree<key_type, value_type, key_of_value, key_compare,
414
+ traits, allow_duplicates, allocator_type>;
415
+
416
+ // The macro TLX_BTREE_FRIENDS can be used by outside class to access
417
+ // the B+ tree internals. This was added for wxBTreeDemo to be able to
418
+ // draw the tree.
419
+ TLX_BTREE_FRIENDS;
420
+
421
+ public:
422
+ // *** Methods
423
+
424
+ //! Default-Constructor of a mutable iterator
425
+ iterator() : curr_leaf(nullptr), curr_slot(0)
426
+ {
427
+ }
428
+
429
+ //! Initializing-Constructor of a mutable iterator
430
+ iterator(typename BTree::LeafNode* l, unsigned short s)
431
+ : curr_leaf(l), curr_slot(s)
432
+ {
433
+ }
434
+
435
+ //! Copy-constructor from a reverse iterator
436
+ iterator(const reverse_iterator& it)
437
+ : curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
438
+ {
439
+ }
440
+
441
+ //! Dereference the iterator.
442
+ reference operator*() const
443
+ {
444
+ return curr_leaf->slotdata[curr_slot];
445
+ }
446
+
447
+ //! Dereference the iterator.
448
+ pointer operator->() const
449
+ {
450
+ return &curr_leaf->slotdata[curr_slot];
451
+ }
452
+
453
+ //! Key of the current slot.
454
+ const key_type& key() const
455
+ {
456
+ return curr_leaf->key(curr_slot);
457
+ }
458
+
459
+ //! Prefix++ advance the iterator to the next slot.
460
+ iterator& operator++()
461
+ {
462
+ if (curr_slot + 1U < curr_leaf->slotuse)
463
+ {
464
+ ++curr_slot;
465
+ }
466
+ else if (curr_leaf->next_leaf != nullptr)
467
+ {
468
+ curr_leaf = curr_leaf->next_leaf;
469
+ curr_slot = 0;
470
+ }
471
+ else
472
+ {
473
+ // this is end()
474
+ curr_slot = curr_leaf->slotuse;
475
+ }
476
+
477
+ return *this;
478
+ }
479
+
480
+ //! Postfix++ advance the iterator to the next slot.
481
+ iterator operator++(int)
482
+ {
483
+ iterator tmp = *this; // copy ourselves
484
+
485
+ if (curr_slot + 1U < curr_leaf->slotuse)
486
+ {
487
+ ++curr_slot;
488
+ }
489
+ else if (curr_leaf->next_leaf != nullptr)
490
+ {
491
+ curr_leaf = curr_leaf->next_leaf;
492
+ curr_slot = 0;
493
+ }
494
+ else
495
+ {
496
+ // this is end()
497
+ curr_slot = curr_leaf->slotuse;
498
+ }
499
+
500
+ return tmp;
501
+ }
502
+
503
+ //! Prefix-- backstep the iterator to the last slot.
504
+ iterator& operator--()
505
+ {
506
+ if (curr_slot > 0)
507
+ {
508
+ --curr_slot;
509
+ }
510
+ else if (curr_leaf->prev_leaf != nullptr)
511
+ {
512
+ curr_leaf = curr_leaf->prev_leaf;
513
+ curr_slot = curr_leaf->slotuse - 1;
514
+ }
515
+ else
516
+ {
517
+ // this is begin()
518
+ curr_slot = 0;
519
+ }
520
+
521
+ return *this;
522
+ }
523
+
524
+ //! Postfix-- backstep the iterator to the last slot.
525
+ iterator operator--(int)
526
+ {
527
+ iterator tmp = *this; // copy ourselves
528
+
529
+ if (curr_slot > 0)
530
+ {
531
+ --curr_slot;
532
+ }
533
+ else if (curr_leaf->prev_leaf != nullptr)
534
+ {
535
+ curr_leaf = curr_leaf->prev_leaf;
536
+ curr_slot = curr_leaf->slotuse - 1;
537
+ }
538
+ else
539
+ {
540
+ // this is begin()
541
+ curr_slot = 0;
542
+ }
543
+
544
+ return tmp;
545
+ }
546
+
547
+ //! Equality of iterators.
548
+ bool operator==(const iterator& x) const
549
+ {
550
+ return (x.curr_leaf == curr_leaf) && (x.curr_slot == curr_slot);
551
+ }
552
+
553
+ //! Inequality of iterators.
554
+ bool operator!=(const iterator& x) const
555
+ {
556
+ return (x.curr_leaf != curr_leaf) || (x.curr_slot != curr_slot);
557
+ }
558
+ };
559
+
560
+ //! STL-like read-only iterator object for B+ tree items. The iterator
561
+ //! points to a specific slot number in a leaf.
562
+ class const_iterator
563
+ {
564
+ public:
565
+ // *** Types
566
+
567
+ //! The key type of the btree. Returned by key().
568
+ typedef typename BTree::key_type key_type;
569
+
570
+ //! The value type of the btree. Returned by operator*().
571
+ typedef typename BTree::value_type value_type;
572
+
573
+ //! Reference to the value_type. STL required.
574
+ typedef const value_type& reference;
575
+
576
+ //! Pointer to the value_type. STL required.
577
+ typedef const value_type* pointer;
578
+
579
+ //! STL-magic iterator category
580
+ typedef std::bidirectional_iterator_tag iterator_category;
581
+
582
+ //! STL-magic
583
+ typedef ptrdiff_t difference_type;
584
+
585
+ //! Our own type
586
+ typedef const_iterator self;
587
+
588
+ private:
589
+ // *** Members
590
+
591
+ //! The currently referenced leaf node of the tree
592
+ const typename BTree::LeafNode* curr_leaf;
593
+
594
+ //! Current key/data slot referenced
595
+ unsigned short curr_slot;
596
+
597
+ //! Friendly to the reverse_const_iterator, so it may access the two
598
+ //! data items directly
599
+ friend class const_reverse_iterator;
600
+
601
+ // The macro TLX_BTREE_FRIENDS can be used by outside class to access
602
+ // the B+ tree internals. This was added for wxBTreeDemo to be able to
603
+ // draw the tree.
604
+ TLX_BTREE_FRIENDS;
605
+
606
+ public:
607
+ // *** Methods
608
+
609
+ //! Default-Constructor of a const iterator
610
+ const_iterator() : curr_leaf(nullptr), curr_slot(0)
611
+ {
612
+ }
613
+
614
+ //! Initializing-Constructor of a const iterator
615
+ const_iterator(const typename BTree::LeafNode* l, unsigned short s)
616
+ : curr_leaf(l), curr_slot(s)
617
+ {
618
+ }
619
+
620
+ //! Copy-constructor from a mutable iterator
621
+ const_iterator(const iterator& it)
622
+ : curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
623
+ {
624
+ }
625
+
626
+ //! Copy-constructor from a mutable reverse iterator
627
+ const_iterator(const reverse_iterator& it)
628
+ : curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
629
+ {
630
+ }
631
+
632
+ //! Copy-constructor from a const reverse iterator
633
+ const_iterator(const const_reverse_iterator& it)
634
+ : curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
635
+ {
636
+ }
637
+
638
+ //! Dereference the iterator.
639
+ reference operator*() const
640
+ {
641
+ return curr_leaf->slotdata[curr_slot];
642
+ }
643
+
644
+ //! Dereference the iterator.
645
+ pointer operator->() const
646
+ {
647
+ return &curr_leaf->slotdata[curr_slot];
648
+ }
649
+
650
+ //! Key of the current slot.
651
+ const key_type& key() const
652
+ {
653
+ return curr_leaf->key(curr_slot);
654
+ }
655
+
656
+ //! Prefix++ advance the iterator to the next slot.
657
+ const_iterator& operator++()
658
+ {
659
+ if (curr_slot + 1U < curr_leaf->slotuse)
660
+ {
661
+ ++curr_slot;
662
+ }
663
+ else if (curr_leaf->next_leaf != nullptr)
664
+ {
665
+ curr_leaf = curr_leaf->next_leaf;
666
+ curr_slot = 0;
667
+ }
668
+ else
669
+ {
670
+ // this is end()
671
+ curr_slot = curr_leaf->slotuse;
672
+ }
673
+
674
+ return *this;
675
+ }
676
+
677
+ //! Postfix++ advance the iterator to the next slot.
678
+ const_iterator operator++(int)
679
+ {
680
+ const_iterator tmp = *this; // copy ourselves
681
+
682
+ if (curr_slot + 1U < curr_leaf->slotuse)
683
+ {
684
+ ++curr_slot;
685
+ }
686
+ else if (curr_leaf->next_leaf != nullptr)
687
+ {
688
+ curr_leaf = curr_leaf->next_leaf;
689
+ curr_slot = 0;
690
+ }
691
+ else
692
+ {
693
+ // this is end()
694
+ curr_slot = curr_leaf->slotuse;
695
+ }
696
+
697
+ return tmp;
698
+ }
699
+
700
+ //! Prefix-- backstep the iterator to the last slot.
701
+ const_iterator& operator--()
702
+ {
703
+ if (curr_slot > 0)
704
+ {
705
+ --curr_slot;
706
+ }
707
+ else if (curr_leaf->prev_leaf != nullptr)
708
+ {
709
+ curr_leaf = curr_leaf->prev_leaf;
710
+ curr_slot = curr_leaf->slotuse - 1;
711
+ }
712
+ else
713
+ {
714
+ // this is begin()
715
+ curr_slot = 0;
716
+ }
717
+
718
+ return *this;
719
+ }
720
+
721
+ //! Postfix-- backstep the iterator to the last slot.
722
+ const_iterator operator--(int)
723
+ {
724
+ const_iterator tmp = *this; // copy ourselves
725
+
726
+ if (curr_slot > 0)
727
+ {
728
+ --curr_slot;
729
+ }
730
+ else if (curr_leaf->prev_leaf != nullptr)
731
+ {
732
+ curr_leaf = curr_leaf->prev_leaf;
733
+ curr_slot = curr_leaf->slotuse - 1;
734
+ }
735
+ else
736
+ {
737
+ // this is begin()
738
+ curr_slot = 0;
739
+ }
740
+
741
+ return tmp;
742
+ }
743
+
744
+ //! Equality of iterators.
745
+ bool operator==(const const_iterator& x) const
746
+ {
747
+ return (x.curr_leaf == curr_leaf) && (x.curr_slot == curr_slot);
748
+ }
749
+
750
+ //! Inequality of iterators.
751
+ bool operator!=(const const_iterator& x) const
752
+ {
753
+ return (x.curr_leaf != curr_leaf) || (x.curr_slot != curr_slot);
754
+ }
755
+ };
756
+
757
+ //! STL-like mutable reverse iterator object for B+ tree items. The
758
+ //! iterator points to a specific slot number in a leaf.
759
+ class reverse_iterator
760
+ {
761
+ public:
762
+ // *** Types
763
+
764
+ //! The key type of the btree. Returned by key().
765
+ typedef typename BTree::key_type key_type;
766
+
767
+ //! The value type of the btree. Returned by operator*().
768
+ typedef typename BTree::value_type value_type;
769
+
770
+ //! Reference to the value_type. STL required.
771
+ typedef value_type& reference;
772
+
773
+ //! Pointer to the value_type. STL required.
774
+ typedef value_type* pointer;
775
+
776
+ //! STL-magic iterator category
777
+ typedef std::bidirectional_iterator_tag iterator_category;
778
+
779
+ //! STL-magic
780
+ typedef ptrdiff_t difference_type;
781
+
782
+ //! Our own type
783
+ typedef reverse_iterator self;
784
+
785
+ private:
786
+ // *** Members
787
+
788
+ //! The currently referenced leaf node of the tree
789
+ typename BTree::LeafNode* curr_leaf;
790
+
791
+ //! One slot past the current key/data slot referenced.
792
+ unsigned short curr_slot;
793
+
794
+ //! Friendly to the const_iterator, so it may access the two data items
795
+ //! directly
796
+ friend class iterator;
797
+
798
+ //! Also friendly to the const_iterator, so it may access the two data
799
+ //! items directly
800
+ friend class const_iterator;
801
+
802
+ //! Also friendly to the const_iterator, so it may access the two data
803
+ //! items directly
804
+ friend class const_reverse_iterator;
805
+
806
+ // The macro TLX_BTREE_FRIENDS can be used by outside class to access
807
+ // the B+ tree internals. This was added for wxBTreeDemo to be able to
808
+ // draw the tree.
809
+ TLX_BTREE_FRIENDS;
810
+
811
+ public:
812
+ // *** Methods
813
+
814
+ //! Default-Constructor of a reverse iterator
815
+ reverse_iterator() : curr_leaf(nullptr), curr_slot(0)
816
+ {
817
+ }
818
+
819
+ //! Initializing-Constructor of a mutable reverse iterator
820
+ reverse_iterator(typename BTree::LeafNode* l, unsigned short s)
821
+ : curr_leaf(l), curr_slot(s)
822
+ {
823
+ }
824
+
825
+ //! Copy-constructor from a mutable iterator
826
+ reverse_iterator(const iterator& it)
827
+ : curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
828
+ {
829
+ }
830
+
831
+ //! Dereference the iterator.
832
+ reference operator*() const
833
+ {
834
+ TLX_BTREE_ASSERT(curr_slot > 0);
835
+ return curr_leaf->slotdata[curr_slot - 1];
836
+ }
837
+
838
+ //! Dereference the iterator.
839
+ pointer operator->() const
840
+ {
841
+ TLX_BTREE_ASSERT(curr_slot > 0);
842
+ return &curr_leaf->slotdata[curr_slot - 1];
843
+ }
844
+
845
+ //! Key of the current slot.
846
+ const key_type& key() const
847
+ {
848
+ TLX_BTREE_ASSERT(curr_slot > 0);
849
+ return curr_leaf->key(curr_slot - 1);
850
+ }
851
+
852
+ //! Prefix++ advance the iterator to the next slot.
853
+ reverse_iterator& operator++()
854
+ {
855
+ if (curr_slot > 1)
856
+ {
857
+ --curr_slot;
858
+ }
859
+ else if (curr_leaf->prev_leaf != nullptr)
860
+ {
861
+ curr_leaf = curr_leaf->prev_leaf;
862
+ curr_slot = curr_leaf->slotuse;
863
+ }
864
+ else
865
+ {
866
+ // this is begin() == rend()
867
+ curr_slot = 0;
868
+ }
869
+
870
+ return *this;
871
+ }
872
+
873
+ //! Postfix++ advance the iterator to the next slot.
874
+ reverse_iterator operator++(int)
875
+ {
876
+ reverse_iterator tmp = *this; // copy ourselves
877
+
878
+ if (curr_slot > 1)
879
+ {
880
+ --curr_slot;
881
+ }
882
+ else if (curr_leaf->prev_leaf != nullptr)
883
+ {
884
+ curr_leaf = curr_leaf->prev_leaf;
885
+ curr_slot = curr_leaf->slotuse;
886
+ }
887
+ else
888
+ {
889
+ // this is begin() == rend()
890
+ curr_slot = 0;
891
+ }
892
+
893
+ return tmp;
894
+ }
895
+
896
+ //! Prefix-- backstep the iterator to the last slot.
897
+ reverse_iterator& operator--()
898
+ {
899
+ if (curr_slot < curr_leaf->slotuse)
900
+ {
901
+ ++curr_slot;
902
+ }
903
+ else if (curr_leaf->next_leaf != nullptr)
904
+ {
905
+ curr_leaf = curr_leaf->next_leaf;
906
+ curr_slot = 1;
907
+ }
908
+ else
909
+ {
910
+ // this is end() == rbegin()
911
+ curr_slot = curr_leaf->slotuse;
912
+ }
913
+
914
+ return *this;
915
+ }
916
+
917
+ //! Postfix-- backstep the iterator to the last slot.
918
+ reverse_iterator operator--(int)
919
+ {
920
+ reverse_iterator tmp = *this; // copy ourselves
921
+
922
+ if (curr_slot < curr_leaf->slotuse)
923
+ {
924
+ ++curr_slot;
925
+ }
926
+ else if (curr_leaf->next_leaf != nullptr)
927
+ {
928
+ curr_leaf = curr_leaf->next_leaf;
929
+ curr_slot = 1;
930
+ }
931
+ else
932
+ {
933
+ // this is end() == rbegin()
934
+ curr_slot = curr_leaf->slotuse;
935
+ }
936
+
937
+ return tmp;
938
+ }
939
+
940
+ //! Equality of iterators.
941
+ bool operator==(const reverse_iterator& x) const
942
+ {
943
+ return (x.curr_leaf == curr_leaf) && (x.curr_slot == curr_slot);
944
+ }
945
+
946
+ //! Inequality of iterators.
947
+ bool operator!=(const reverse_iterator& x) const
948
+ {
949
+ return (x.curr_leaf != curr_leaf) || (x.curr_slot != curr_slot);
950
+ }
951
+ };
952
+
953
+ //! STL-like read-only reverse iterator object for B+ tree items. The
954
+ //! iterator points to a specific slot number in a leaf.
955
+ class const_reverse_iterator
956
+ {
957
+ public:
958
+ // *** Types
959
+
960
+ //! The key type of the btree. Returned by key().
961
+ typedef typename BTree::key_type key_type;
962
+
963
+ //! The value type of the btree. Returned by operator*().
964
+ typedef typename BTree::value_type value_type;
965
+
966
+ //! Reference to the value_type. STL required.
967
+ typedef const value_type& reference;
968
+
969
+ //! Pointer to the value_type. STL required.
970
+ typedef const value_type* pointer;
971
+
972
+ //! STL-magic iterator category
973
+ typedef std::bidirectional_iterator_tag iterator_category;
974
+
975
+ //! STL-magic
976
+ typedef ptrdiff_t difference_type;
977
+
978
+ //! Our own type
979
+ typedef const_reverse_iterator self;
980
+
981
+ private:
982
+ // *** Members
983
+
984
+ //! The currently referenced leaf node of the tree
985
+ const typename BTree::LeafNode* curr_leaf;
986
+
987
+ //! One slot past the current key/data slot referenced.
988
+ unsigned short curr_slot;
989
+
990
+ //! Friendly to the const_iterator, so it may access the two data items
991
+ //! directly.
992
+ friend class reverse_iterator;
993
+
994
+ // The macro TLX_BTREE_FRIENDS can be used by outside class to access
995
+ // the B+ tree internals. This was added for wxBTreeDemo to be able to
996
+ // draw the tree.
997
+ TLX_BTREE_FRIENDS;
998
+
999
+ public:
1000
+ // *** Methods
1001
+
1002
+ //! Default-Constructor of a const reverse iterator.
1003
+ const_reverse_iterator() : curr_leaf(nullptr), curr_slot(0)
1004
+ {
1005
+ }
1006
+
1007
+ //! Initializing-Constructor of a const reverse iterator.
1008
+ const_reverse_iterator(const typename BTree::LeafNode* l,
1009
+ unsigned short s)
1010
+ : curr_leaf(l), curr_slot(s)
1011
+ {
1012
+ }
1013
+
1014
+ //! Copy-constructor from a mutable iterator.
1015
+ const_reverse_iterator(const iterator& it)
1016
+ : curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
1017
+ {
1018
+ }
1019
+
1020
+ //! Copy-constructor from a const iterator.
1021
+ const_reverse_iterator(const const_iterator& it)
1022
+ : curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
1023
+ {
1024
+ }
1025
+
1026
+ //! Copy-constructor from a mutable reverse iterator.
1027
+ const_reverse_iterator(const reverse_iterator& it)
1028
+ : curr_leaf(it.curr_leaf), curr_slot(it.curr_slot)
1029
+ {
1030
+ }
1031
+
1032
+ //! Dereference the iterator.
1033
+ reference operator*() const
1034
+ {
1035
+ TLX_BTREE_ASSERT(curr_slot > 0);
1036
+ return curr_leaf->slotdata[curr_slot - 1];
1037
+ }
1038
+
1039
+ //! Dereference the iterator.
1040
+ pointer operator->() const
1041
+ {
1042
+ TLX_BTREE_ASSERT(curr_slot > 0);
1043
+ return &curr_leaf->slotdata[curr_slot - 1];
1044
+ }
1045
+
1046
+ //! Key of the current slot.
1047
+ const key_type& key() const
1048
+ {
1049
+ TLX_BTREE_ASSERT(curr_slot > 0);
1050
+ return curr_leaf->key(curr_slot - 1);
1051
+ }
1052
+
1053
+ //! Prefix++ advance the iterator to the previous slot.
1054
+ const_reverse_iterator& operator++()
1055
+ {
1056
+ if (curr_slot > 1)
1057
+ {
1058
+ --curr_slot;
1059
+ }
1060
+ else if (curr_leaf->prev_leaf != nullptr)
1061
+ {
1062
+ curr_leaf = curr_leaf->prev_leaf;
1063
+ curr_slot = curr_leaf->slotuse;
1064
+ }
1065
+ else
1066
+ {
1067
+ // this is begin() == rend()
1068
+ curr_slot = 0;
1069
+ }
1070
+
1071
+ return *this;
1072
+ }
1073
+
1074
+ //! Postfix++ advance the iterator to the previous slot.
1075
+ const_reverse_iterator operator++(int)
1076
+ {
1077
+ const_reverse_iterator tmp = *this; // copy ourselves
1078
+
1079
+ if (curr_slot > 1)
1080
+ {
1081
+ --curr_slot;
1082
+ }
1083
+ else if (curr_leaf->prev_leaf != nullptr)
1084
+ {
1085
+ curr_leaf = curr_leaf->prev_leaf;
1086
+ curr_slot = curr_leaf->slotuse;
1087
+ }
1088
+ else
1089
+ {
1090
+ // this is begin() == rend()
1091
+ curr_slot = 0;
1092
+ }
1093
+
1094
+ return tmp;
1095
+ }
1096
+
1097
+ //! Prefix-- backstep the iterator to the next slot.
1098
+ const_reverse_iterator& operator--()
1099
+ {
1100
+ if (curr_slot < curr_leaf->slotuse)
1101
+ {
1102
+ ++curr_slot;
1103
+ }
1104
+ else if (curr_leaf->next_leaf != nullptr)
1105
+ {
1106
+ curr_leaf = curr_leaf->next_leaf;
1107
+ curr_slot = 1;
1108
+ }
1109
+ else
1110
+ {
1111
+ // this is end() == rbegin()
1112
+ curr_slot = curr_leaf->slotuse;
1113
+ }
1114
+
1115
+ return *this;
1116
+ }
1117
+
1118
+ //! Postfix-- backstep the iterator to the next slot.
1119
+ const_reverse_iterator operator--(int)
1120
+ {
1121
+ const_reverse_iterator tmp = *this; // copy ourselves
1122
+
1123
+ if (curr_slot < curr_leaf->slotuse)
1124
+ {
1125
+ ++curr_slot;
1126
+ }
1127
+ else if (curr_leaf->next_leaf != nullptr)
1128
+ {
1129
+ curr_leaf = curr_leaf->next_leaf;
1130
+ curr_slot = 1;
1131
+ }
1132
+ else
1133
+ {
1134
+ // this is end() == rbegin()
1135
+ curr_slot = curr_leaf->slotuse;
1136
+ }
1137
+
1138
+ return tmp;
1139
+ }
1140
+
1141
+ //! Equality of iterators.
1142
+ bool operator==(const const_reverse_iterator& x) const
1143
+ {
1144
+ return (x.curr_leaf == curr_leaf) && (x.curr_slot == curr_slot);
1145
+ }
1146
+
1147
+ //! Inequality of iterators.
1148
+ bool operator!=(const const_reverse_iterator& x) const
1149
+ {
1150
+ return (x.curr_leaf != curr_leaf) || (x.curr_slot != curr_slot);
1151
+ }
1152
+ };
1153
+
1154
+ //! \}
1155
+
1156
+ public:
1157
+ //! \name Small Statistics Structure
1158
+ //! \{
1159
+
1160
+ /*!
1161
+ * A small struct containing basic statistics about the B+ tree. It can be
1162
+ * fetched using get_stats().
1163
+ */
1164
+ struct tree_stats
1165
+ {
1166
+ //! Number of items in the B+ tree
1167
+ size_type size = 0;
1168
+
1169
+ //! Number of leaves in the B+ tree
1170
+ size_type leaves = 0;
1171
+
1172
+ //! Number of inner nodes in the B+ tree
1173
+ size_type inner_nodes = 0;
1174
+
1175
+ //! Base B+ tree parameter: The number of key/data slots in each leaf
1176
+ static const unsigned short leaf_slots = Self::leaf_slotmax;
1177
+
1178
+ //! Base B+ tree parameter: The number of key slots in each inner node.
1179
+ static const unsigned short inner_slots = Self::inner_slotmax;
1180
+
1181
+ //! Return the total number of nodes
1182
+ size_type nodes() const
1183
+ {
1184
+ return inner_nodes + leaves;
1185
+ }
1186
+
1187
+ //! Return the average fill of leaves
1188
+ double avgfill_leaves() const
1189
+ {
1190
+ return static_cast<double>(size) / (leaves * leaf_slots);
1191
+ }
1192
+ };
1193
+
1194
+ //! \}
1195
+
1196
+ private:
1197
+ //! \name Tree Object Data Members
1198
+ //! \{
1199
+
1200
+ //! Pointer to the B+ tree's root node, either leaf or inner node.
1201
+ node* root_;
1202
+
1203
+ //! Pointer to first leaf in the double linked leaf chain.
1204
+ LeafNode* head_leaf_;
1205
+
1206
+ //! Pointer to last leaf in the double linked leaf chain.
1207
+ LeafNode* tail_leaf_;
1208
+
1209
+ //! Other small statistics about the B+ tree.
1210
+ tree_stats stats_;
1211
+
1212
+ //! Key comparison object. More comparison functions are generated from
1213
+ //! this < relation.
1214
+ key_compare key_less_;
1215
+
1216
+ //! Memory allocator.
1217
+ allocator_type allocator_;
1218
+
1219
+ //! \}
1220
+
1221
+ public:
1222
+ //! \name Constructors and Destructor
1223
+ //! \{
1224
+
1225
+ //! Default constructor initializing an empty B+ tree with the standard key
1226
+ //! comparison function.
1227
+ explicit BTree(const allocator_type& alloc = allocator_type())
1228
+ : root_(nullptr),
1229
+ head_leaf_(nullptr),
1230
+ tail_leaf_(nullptr),
1231
+ allocator_(alloc)
1232
+ {
1233
+ }
1234
+
1235
+ //! Constructor initializing an empty B+ tree with a special key
1236
+ //! comparison object.
1237
+ explicit BTree(const key_compare& kcf,
1238
+ const allocator_type& alloc = allocator_type())
1239
+ : root_(nullptr),
1240
+ head_leaf_(nullptr),
1241
+ tail_leaf_(nullptr),
1242
+ key_less_(kcf),
1243
+ allocator_(alloc)
1244
+ {
1245
+ }
1246
+
1247
+ //! Constructor initializing a B+ tree with the range [first,last). The
1248
+ //! range need not be sorted. To create a B+ tree from a sorted range, use
1249
+ //! bulk_load().
1250
+ template <class InputIterator>
1251
+ BTree(InputIterator first, InputIterator last,
1252
+ const allocator_type& alloc = allocator_type())
1253
+ : root_(nullptr),
1254
+ head_leaf_(nullptr),
1255
+ tail_leaf_(nullptr),
1256
+ allocator_(alloc)
1257
+ {
1258
+ insert(first, last);
1259
+ }
1260
+
1261
+ //! Constructor initializing a B+ tree with the range [first,last) and a
1262
+ //! special key comparison object. The range need not be sorted. To create
1263
+ //! a B+ tree from a sorted range, use bulk_load().
1264
+ template <class InputIterator>
1265
+ BTree(InputIterator first, InputIterator last, const key_compare& kcf,
1266
+ const allocator_type& alloc = allocator_type())
1267
+ : root_(nullptr),
1268
+ head_leaf_(nullptr),
1269
+ tail_leaf_(nullptr),
1270
+ key_less_(kcf),
1271
+ allocator_(alloc)
1272
+ {
1273
+ insert(first, last);
1274
+ }
1275
+
1276
+ //! Frees up all used B+ tree memory pages
1277
+ ~BTree()
1278
+ {
1279
+ clear();
1280
+ }
1281
+
1282
+ //! Fast swapping of two identical B+ tree objects.
1283
+ void swap(BTree& from) noexcept
1284
+ {
1285
+ std::swap(root_, from.root_);
1286
+ std::swap(head_leaf_, from.head_leaf_);
1287
+ std::swap(tail_leaf_, from.tail_leaf_);
1288
+ std::swap(stats_, from.stats_);
1289
+ std::swap(key_less_, from.key_less_);
1290
+ std::swap(allocator_, from.allocator_);
1291
+ }
1292
+
1293
+ //! \}
1294
+
1295
+ public:
1296
+ //! \name Key and Value Comparison Function Objects
1297
+ //! \{
1298
+
1299
+ //! Function class to compare value_type objects. Required by the STL
1300
+ class value_compare
1301
+ {
1302
+ private:
1303
+ //! Key comparison function from the template parameter
1304
+ key_compare key_comp;
1305
+
1306
+ //! Constructor called from BTree::value_comp()
1307
+ explicit value_compare(key_compare kc) : key_comp(kc)
1308
+ {
1309
+ }
1310
+
1311
+ //! Friendly to the btree class so it may call the constructor
1312
+ friend class BTree<key_type, value_type, key_of_value, key_compare,
1313
+ traits, allow_duplicates, allocator_type>;
1314
+
1315
+ public:
1316
+ //! Function call "less"-operator resulting in true if x < y.
1317
+ bool operator()(const value_type& x, const value_type& y) const
1318
+ {
1319
+ return key_comp(x.first, y.first);
1320
+ }
1321
+ };
1322
+
1323
+ //! Constant access to the key comparison object sorting the B+ tree.
1324
+ key_compare key_comp() const
1325
+ {
1326
+ return key_less_;
1327
+ }
1328
+
1329
+ //! Constant access to a constructed value_type comparison object. Required
1330
+ //! by the STL.
1331
+ value_compare value_comp() const
1332
+ {
1333
+ return value_compare(key_less_);
1334
+ }
1335
+
1336
+ //! \}
1337
+
1338
+ private:
1339
+ //! \name Convenient Key Comparison Functions Generated From key_less
1340
+ //! \{
1341
+
1342
+ //! True if a < b ? "constructed" from key_less_()
1343
+ bool key_less(const key_type& a, const key_type& b) const
1344
+ {
1345
+ return key_less_(a, b);
1346
+ }
1347
+
1348
+ //! True if a <= b ? constructed from key_less()
1349
+ bool key_lessequal(const key_type& a, const key_type& b) const
1350
+ {
1351
+ return !key_less_(b, a);
1352
+ }
1353
+
1354
+ //! True if a > b ? constructed from key_less()
1355
+ bool key_greater(const key_type& a, const key_type& b) const
1356
+ {
1357
+ return key_less_(b, a);
1358
+ }
1359
+
1360
+ //! True if a >= b ? constructed from key_less()
1361
+ bool key_greaterequal(const key_type& a, const key_type& b) const
1362
+ {
1363
+ return !key_less_(a, b);
1364
+ }
1365
+
1366
+ //! True if a == b ? constructed from key_less(). This requires the <
1367
+ //! relation to be a total order, otherwise the B+ tree cannot be sorted.
1368
+ bool key_equal(const key_type& a, const key_type& b) const
1369
+ {
1370
+ return !key_less_(a, b) && !key_less_(b, a);
1371
+ }
1372
+
1373
+ //! \}
1374
+
1375
+ public:
1376
+ //! \name Allocators
1377
+ //! \{
1378
+
1379
+ //! Return the base node allocator provided during construction.
1380
+ allocator_type get_allocator() const
1381
+ {
1382
+ return allocator_;
1383
+ }
1384
+
1385
+ //! \}
1386
+
1387
+ private:
1388
+ //! \name Node Object Allocation and Deallocation Functions
1389
+ //! \{
1390
+
1391
+ //! Return an allocator for LeafNode objects.
1392
+ typename LeafNode::alloc_type leaf_node_allocator()
1393
+ {
1394
+ return typename LeafNode::alloc_type(allocator_);
1395
+ }
1396
+
1397
+ //! Return an allocator for InnerNode objects.
1398
+ typename InnerNode::alloc_type inner_node_allocator()
1399
+ {
1400
+ return typename InnerNode::alloc_type(allocator_);
1401
+ }
1402
+
1403
+ //! Allocate and initialize a leaf node
1404
+ LeafNode* allocate_leaf()
1405
+ {
1406
+ LeafNode* n = new (leaf_node_allocator().allocate(1)) LeafNode();
1407
+ n->initialize();
1408
+ stats_.leaves++;
1409
+ return n;
1410
+ }
1411
+
1412
+ //! Allocate and initialize an inner node
1413
+ InnerNode* allocate_inner(unsigned short level)
1414
+ {
1415
+ InnerNode* n = new (inner_node_allocator().allocate(1)) InnerNode();
1416
+ n->initialize(level);
1417
+ stats_.inner_nodes++;
1418
+ return n;
1419
+ }
1420
+
1421
+ //! Correctly free either inner or leaf node, destructs all contained key
1422
+ //! and value objects.
1423
+ void free_node(node* n)
1424
+ {
1425
+ if (n->is_leafnode())
1426
+ {
1427
+ LeafNode* ln = static_cast<LeafNode*>(n);
1428
+ typename LeafNode::alloc_type a(leaf_node_allocator());
1429
+ std::allocator_traits<typename LeafNode::alloc_type>::destroy(a,
1430
+ ln);
1431
+ std::allocator_traits<typename LeafNode::alloc_type>::deallocate(
1432
+ a, ln, 1);
1433
+ stats_.leaves--;
1434
+ }
1435
+ else
1436
+ {
1437
+ InnerNode* in = static_cast<InnerNode*>(n);
1438
+ typename InnerNode::alloc_type a(inner_node_allocator());
1439
+ std::allocator_traits<typename InnerNode::alloc_type>::destroy(a,
1440
+ in);
1441
+ std::allocator_traits<typename InnerNode::alloc_type>::deallocate(
1442
+ a, in, 1);
1443
+ stats_.inner_nodes--;
1444
+ }
1445
+ }
1446
+
1447
+ //! \}
1448
+
1449
+ public:
1450
+ //! \name Fast Destruction of the B+ Tree
1451
+ //! \{
1452
+
1453
+ //! Frees all key/data pairs and all nodes of the tree.
1454
+ void clear()
1455
+ {
1456
+ if (root_)
1457
+ {
1458
+ clear_recursive(root_);
1459
+ free_node(root_);
1460
+
1461
+ root_ = nullptr;
1462
+ head_leaf_ = tail_leaf_ = nullptr;
1463
+
1464
+ stats_ = tree_stats();
1465
+ }
1466
+
1467
+ TLX_BTREE_ASSERT(stats_.size == 0);
1468
+ }
1469
+
1470
+ private:
1471
+ //! Recursively free up nodes.
1472
+ void clear_recursive(node* n)
1473
+ {
1474
+ if (n->is_leafnode())
1475
+ {
1476
+ LeafNode* leafnode = static_cast<LeafNode*>(n);
1477
+
1478
+ for (unsigned short slot = 0; slot < leafnode->slotuse; ++slot)
1479
+ {
1480
+ // data objects are deleted by LeafNode's destructor
1481
+ }
1482
+ }
1483
+ else
1484
+ {
1485
+ InnerNode* innernode = static_cast<InnerNode*>(n);
1486
+
1487
+ for (unsigned short slot = 0; slot < innernode->slotuse + 1; ++slot)
1488
+ {
1489
+ clear_recursive(innernode->childid[slot]);
1490
+ free_node(innernode->childid[slot]);
1491
+ }
1492
+ }
1493
+ }
1494
+
1495
+ //! \}
1496
+
1497
+ public:
1498
+ //! \name STL Iterator Construction Functions
1499
+ //! \{
1500
+
1501
+ //! Constructs a read/data-write iterator that points to the first slot in
1502
+ //! the first leaf of the B+ tree.
1503
+ iterator begin()
1504
+ {
1505
+ return iterator(head_leaf_, 0);
1506
+ }
1507
+
1508
+ //! Constructs a read/data-write iterator that points to the first invalid
1509
+ //! slot in the last leaf of the B+ tree.
1510
+ iterator end()
1511
+ {
1512
+ return iterator(tail_leaf_, tail_leaf_ ? tail_leaf_->slotuse : 0);
1513
+ }
1514
+
1515
+ //! Constructs a read-only constant iterator that points to the first slot
1516
+ //! in the first leaf of the B+ tree.
1517
+ const_iterator begin() const
1518
+ {
1519
+ return const_iterator(head_leaf_, 0);
1520
+ }
1521
+
1522
+ //! Constructs a read-only constant iterator that points to the first
1523
+ //! invalid slot in the last leaf of the B+ tree.
1524
+ const_iterator end() const
1525
+ {
1526
+ return const_iterator(tail_leaf_, tail_leaf_ ? tail_leaf_->slotuse : 0);
1527
+ }
1528
+
1529
+ //! Constructs a read/data-write reverse iterator that points to the first
1530
+ //! invalid slot in the last leaf of the B+ tree. Uses STL magic.
1531
+ reverse_iterator rbegin()
1532
+ {
1533
+ return reverse_iterator(end());
1534
+ }
1535
+
1536
+ //! Constructs a read/data-write reverse iterator that points to the first
1537
+ //! slot in the first leaf of the B+ tree. Uses STL magic.
1538
+ reverse_iterator rend()
1539
+ {
1540
+ return reverse_iterator(begin());
1541
+ }
1542
+
1543
+ //! Constructs a read-only reverse iterator that points to the first
1544
+ //! invalid slot in the last leaf of the B+ tree. Uses STL magic.
1545
+ const_reverse_iterator rbegin() const
1546
+ {
1547
+ return const_reverse_iterator(end());
1548
+ }
1549
+
1550
+ //! Constructs a read-only reverse iterator that points to the first slot
1551
+ //! in the first leaf of the B+ tree. Uses STL magic.
1552
+ const_reverse_iterator rend() const
1553
+ {
1554
+ return const_reverse_iterator(begin());
1555
+ }
1556
+
1557
+ //! \}
1558
+
1559
+ private:
1560
+ //! \name B+ Tree Node Binary Search Functions
1561
+ //! \{
1562
+
1563
+ //! Searches for the first key in the node n greater or equal to key. Uses
1564
+ //! binary search with an optional linear self-verification. This is a
1565
+ //! template function, because the slotkey array is located at different
1566
+ //! places in LeafNode and InnerNode.
1567
+ template <typename node_type>
1568
+ unsigned short find_lower(const node_type* n, const key_type& key) const
1569
+ {
1570
+ if (sizeof(*n) > traits::binsearch_threshold)
1571
+ {
1572
+ if (n->slotuse == 0)
1573
+ return 0;
1574
+
1575
+ unsigned short lo = 0, hi = n->slotuse;
1576
+
1577
+ while (lo < hi)
1578
+ {
1579
+ unsigned short mid = (lo + hi) >> 1;
1580
+
1581
+ if (key_lessequal(key, n->key(mid)))
1582
+ {
1583
+ hi = mid; // key <= mid
1584
+ }
1585
+ else
1586
+ {
1587
+ lo = mid + 1; // key > mid
1588
+ }
1589
+ }
1590
+
1591
+ TLX_BTREE_PRINT("BTree::find_lower: on " << n << " key " << key
1592
+ << " -> " << lo << " / "
1593
+ << hi);
1594
+
1595
+ // verify result using simple linear search
1596
+ if (self_verify)
1597
+ {
1598
+ unsigned short i = 0;
1599
+ while (i < n->slotuse && key_less(n->key(i), key))
1600
+ ++i;
1601
+
1602
+ TLX_BTREE_PRINT("BTree::find_lower: testfind: " << i);
1603
+ TLX_BTREE_ASSERT(i == lo);
1604
+ }
1605
+
1606
+ return lo;
1607
+ }
1608
+
1609
+ // for nodes <= binsearch_threshold do linear search.
1610
+ unsigned short lo = 0;
1611
+ while (lo < n->slotuse && key_less(n->key(lo), key))
1612
+ ++lo;
1613
+ return lo;
1614
+ }
1615
+
1616
+ //! Searches for the first key in the node n greater than key. Uses binary
1617
+ //! search with an optional linear self-verification. This is a template
1618
+ //! function, because the slotkey array is located at different places in
1619
+ //! LeafNode and InnerNode.
1620
+ template <typename node_type>
1621
+ unsigned short find_upper(const node_type* n, const key_type& key) const
1622
+ {
1623
+ if (sizeof(*n) > traits::binsearch_threshold)
1624
+ {
1625
+ if (n->slotuse == 0)
1626
+ return 0;
1627
+
1628
+ unsigned short lo = 0, hi = n->slotuse;
1629
+
1630
+ while (lo < hi)
1631
+ {
1632
+ unsigned short mid = (lo + hi) >> 1;
1633
+
1634
+ if (key_less(key, n->key(mid)))
1635
+ {
1636
+ hi = mid; // key < mid
1637
+ }
1638
+ else
1639
+ {
1640
+ lo = mid + 1; // key >= mid
1641
+ }
1642
+ }
1643
+
1644
+ TLX_BTREE_PRINT("BTree::find_upper: on " << n << " key " << key
1645
+ << " -> " << lo << " / "
1646
+ << hi);
1647
+
1648
+ // verify result using simple linear search
1649
+ if (self_verify)
1650
+ {
1651
+ unsigned short i = 0;
1652
+ while (i < n->slotuse && key_lessequal(n->key(i), key))
1653
+ ++i;
1654
+
1655
+ TLX_BTREE_PRINT("BTree::find_upper testfind: " << i);
1656
+ TLX_BTREE_ASSERT(i == hi);
1657
+ }
1658
+
1659
+ return lo;
1660
+ }
1661
+
1662
+ // for nodes <= binsearch_threshold do linear search.
1663
+ unsigned short lo = 0;
1664
+ while (lo < n->slotuse && key_lessequal(n->key(lo), key))
1665
+ ++lo;
1666
+ return lo;
1667
+ }
1668
+
1669
+ //! \}
1670
+
1671
+ public:
1672
+ //! \name Access Functions to the Item Count
1673
+ //! \{
1674
+
1675
+ //! Return the number of key/data pairs in the B+ tree
1676
+ size_type size() const
1677
+ {
1678
+ return stats_.size;
1679
+ }
1680
+
1681
+ //! Returns true if there is at least one key/data pair in the B+ tree
1682
+ bool empty() const
1683
+ {
1684
+ return (size() == size_type(0));
1685
+ }
1686
+
1687
+ //! Returns the largest possible size of the B+ Tree. This is just a
1688
+ //! function required by the STL standard, the B+ Tree can hold more items.
1689
+ size_type max_size() const
1690
+ {
1691
+ return size_type(-1);
1692
+ }
1693
+
1694
+ //! Return a const reference to the current statistics.
1695
+ const struct tree_stats& get_stats() const
1696
+ {
1697
+ return stats_;
1698
+ }
1699
+
1700
+ //! \}
1701
+
1702
+ public:
1703
+ //! \name STL Access Functions Querying the Tree by Descending to a Leaf
1704
+ //! \{
1705
+
1706
+ //! Non-STL function checking whether a key is in the B+ tree. The same as
1707
+ //! (find(k) != end()) or (count() != 0).
1708
+ bool exists(const key_type& key) const
1709
+ {
1710
+ const node* n = root_;
1711
+ if (!n)
1712
+ return false;
1713
+
1714
+ while (!n->is_leafnode())
1715
+ {
1716
+ const InnerNode* inner = static_cast<const InnerNode*>(n);
1717
+ unsigned short slot = find_lower(inner, key);
1718
+
1719
+ n = inner->childid[slot];
1720
+ }
1721
+
1722
+ const LeafNode* leaf = static_cast<const LeafNode*>(n);
1723
+
1724
+ unsigned short slot = find_lower(leaf, key);
1725
+ return (slot < leaf->slotuse && key_equal(key, leaf->key(slot)));
1726
+ }
1727
+
1728
+ //! Tries to locate a key in the B+ tree and returns an iterator to the
1729
+ //! key/data slot if found. If unsuccessful it returns end().
1730
+ iterator find(const key_type& key)
1731
+ {
1732
+ node* n = root_;
1733
+ if (!n)
1734
+ return end();
1735
+
1736
+ while (!n->is_leafnode())
1737
+ {
1738
+ const InnerNode* inner = static_cast<const InnerNode*>(n);
1739
+ unsigned short slot = find_lower(inner, key);
1740
+
1741
+ n = inner->childid[slot];
1742
+ }
1743
+
1744
+ LeafNode* leaf = static_cast<LeafNode*>(n);
1745
+
1746
+ unsigned short slot = find_lower(leaf, key);
1747
+ return (slot < leaf->slotuse && key_equal(key, leaf->key(slot))) ?
1748
+ iterator(leaf, slot) :
1749
+ end();
1750
+ }
1751
+
1752
+ //! Tries to locate a key in the B+ tree and returns an constant iterator to
1753
+ //! the key/data slot if found. If unsuccessful it returns end().
1754
+ const_iterator find(const key_type& key) const
1755
+ {
1756
+ const node* n = root_;
1757
+ if (!n)
1758
+ return end();
1759
+
1760
+ while (!n->is_leafnode())
1761
+ {
1762
+ const InnerNode* inner = static_cast<const InnerNode*>(n);
1763
+ unsigned short slot = find_lower(inner, key);
1764
+
1765
+ n = inner->childid[slot];
1766
+ }
1767
+
1768
+ const LeafNode* leaf = static_cast<const LeafNode*>(n);
1769
+
1770
+ unsigned short slot = find_lower(leaf, key);
1771
+ return (slot < leaf->slotuse && key_equal(key, leaf->key(slot))) ?
1772
+ const_iterator(leaf, slot) :
1773
+ end();
1774
+ }
1775
+
1776
+ //! Tries to locate a key in the B+ tree and returns the number of identical
1777
+ //! key entries found.
1778
+ size_type count(const key_type& key) const
1779
+ {
1780
+ const node* n = root_;
1781
+ if (!n)
1782
+ return 0;
1783
+
1784
+ while (!n->is_leafnode())
1785
+ {
1786
+ const InnerNode* inner = static_cast<const InnerNode*>(n);
1787
+ unsigned short slot = find_lower(inner, key);
1788
+
1789
+ n = inner->childid[slot];
1790
+ }
1791
+
1792
+ const LeafNode* leaf = static_cast<const LeafNode*>(n);
1793
+
1794
+ unsigned short slot = find_lower(leaf, key);
1795
+ size_type num = 0;
1796
+
1797
+ while (leaf && slot < leaf->slotuse && key_equal(key, leaf->key(slot)))
1798
+ {
1799
+ ++num;
1800
+ if (++slot >= leaf->slotuse)
1801
+ {
1802
+ leaf = leaf->next_leaf;
1803
+ slot = 0;
1804
+ }
1805
+ }
1806
+
1807
+ return num;
1808
+ }
1809
+
1810
+ //! Searches the B+ tree and returns an iterator to the first pair equal to
1811
+ //! or greater than key, or end() if all keys are smaller.
1812
+ iterator lower_bound(const key_type& key)
1813
+ {
1814
+ node* n = root_;
1815
+ if (!n)
1816
+ return end();
1817
+
1818
+ while (!n->is_leafnode())
1819
+ {
1820
+ const InnerNode* inner = static_cast<const InnerNode*>(n);
1821
+ unsigned short slot = find_lower(inner, key);
1822
+
1823
+ n = inner->childid[slot];
1824
+ }
1825
+
1826
+ LeafNode* leaf = static_cast<LeafNode*>(n);
1827
+
1828
+ unsigned short slot = find_lower(leaf, key);
1829
+ return iterator(leaf, slot);
1830
+ }
1831
+
1832
+ //! Searches the B+ tree and returns a constant iterator to the first pair
1833
+ //! equal to or greater than key, or end() if all keys are smaller.
1834
+ const_iterator lower_bound(const key_type& key) const
1835
+ {
1836
+ const node* n = root_;
1837
+ if (!n)
1838
+ return end();
1839
+
1840
+ while (!n->is_leafnode())
1841
+ {
1842
+ const InnerNode* inner = static_cast<const InnerNode*>(n);
1843
+ unsigned short slot = find_lower(inner, key);
1844
+
1845
+ n = inner->childid[slot];
1846
+ }
1847
+
1848
+ const LeafNode* leaf = static_cast<const LeafNode*>(n);
1849
+
1850
+ unsigned short slot = find_lower(leaf, key);
1851
+ return const_iterator(leaf, slot);
1852
+ }
1853
+
1854
+ //! Searches the B+ tree and returns an iterator to the first pair greater
1855
+ //! than key, or end() if all keys are smaller or equal.
1856
+ iterator upper_bound(const key_type& key)
1857
+ {
1858
+ node* n = root_;
1859
+ if (!n)
1860
+ return end();
1861
+
1862
+ while (!n->is_leafnode())
1863
+ {
1864
+ const InnerNode* inner = static_cast<const InnerNode*>(n);
1865
+ unsigned short slot = find_upper(inner, key);
1866
+
1867
+ n = inner->childid[slot];
1868
+ }
1869
+
1870
+ LeafNode* leaf = static_cast<LeafNode*>(n);
1871
+
1872
+ unsigned short slot = find_upper(leaf, key);
1873
+ return iterator(leaf, slot);
1874
+ }
1875
+
1876
+ //! Searches the B+ tree and returns a constant iterator to the first pair
1877
+ //! greater than key, or end() if all keys are smaller or equal.
1878
+ const_iterator upper_bound(const key_type& key) const
1879
+ {
1880
+ const node* n = root_;
1881
+ if (!n)
1882
+ return end();
1883
+
1884
+ while (!n->is_leafnode())
1885
+ {
1886
+ const InnerNode* inner = static_cast<const InnerNode*>(n);
1887
+ unsigned short slot = find_upper(inner, key);
1888
+
1889
+ n = inner->childid[slot];
1890
+ }
1891
+
1892
+ const LeafNode* leaf = static_cast<const LeafNode*>(n);
1893
+
1894
+ unsigned short slot = find_upper(leaf, key);
1895
+ return const_iterator(leaf, slot);
1896
+ }
1897
+
1898
+ //! Searches the B+ tree and returns both lower_bound() and upper_bound().
1899
+ std::pair<iterator, iterator> equal_range(const key_type& key)
1900
+ {
1901
+ return std::pair<iterator, iterator>(lower_bound(key),
1902
+ upper_bound(key));
1903
+ }
1904
+
1905
+ //! Searches the B+ tree and returns both lower_bound() and upper_bound().
1906
+ std::pair<const_iterator, const_iterator> equal_range(
1907
+ const key_type& key) const
1908
+ {
1909
+ return std::pair<const_iterator, const_iterator>(lower_bound(key),
1910
+ upper_bound(key));
1911
+ }
1912
+
1913
+ //! \}
1914
+
1915
+ public:
1916
+ //! \name B+ Tree Object Comparison Functions
1917
+ //! \{
1918
+
1919
+ //! Equality relation of B+ trees of the same type. B+ trees of the same
1920
+ //! size and equal elements (both key and data) are considered equal. Beware
1921
+ //! of the random ordering of duplicate keys.
1922
+ bool operator==(const BTree& other) const
1923
+ {
1924
+ return (size() == other.size()) &&
1925
+ std::equal(begin(), end(), other.begin());
1926
+ }
1927
+
1928
+ //! Inequality relation. Based on operator==.
1929
+ bool operator!=(const BTree& other) const
1930
+ {
1931
+ return !(*this == other);
1932
+ }
1933
+
1934
+ //! Total ordering relation of B+ trees of the same type. It uses
1935
+ //! std::lexicographical_compare() for the actual comparison of elements.
1936
+ bool operator<(const BTree& other) const
1937
+ {
1938
+ return std::lexicographical_compare(begin(), end(), other.begin(),
1939
+ other.end());
1940
+ }
1941
+
1942
+ //! Greater relation. Based on operator<.
1943
+ bool operator>(const BTree& other) const
1944
+ {
1945
+ return other < *this;
1946
+ }
1947
+
1948
+ //! Less-equal relation. Based on operator<.
1949
+ bool operator<=(const BTree& other) const
1950
+ {
1951
+ return !(other < *this);
1952
+ }
1953
+
1954
+ //! Greater-equal relation. Based on operator<.
1955
+ bool operator>=(const BTree& other) const
1956
+ {
1957
+ return !(*this < other);
1958
+ }
1959
+
1960
+ //! \}
1961
+
1962
+ public:
1963
+ //! \name Fast Copy: Assign Operator and Copy Constructors
1964
+ //! \{
1965
+
1966
+ //! Assignment operator. All the key/data pairs are copied.
1967
+ BTree& operator=(const BTree& other)
1968
+ {
1969
+ if (this != &other)
1970
+ {
1971
+ clear();
1972
+
1973
+ key_less_ = other.key_comp();
1974
+ allocator_ = other.get_allocator();
1975
+
1976
+ if (other.size() != 0)
1977
+ {
1978
+ stats_.leaves = stats_.inner_nodes = 0;
1979
+ if (other.root_)
1980
+ {
1981
+ root_ = copy_recursive(other.root_);
1982
+ }
1983
+ stats_ = other.stats_;
1984
+ }
1985
+
1986
+ if (self_verify)
1987
+ verify();
1988
+ }
1989
+ return *this;
1990
+ }
1991
+
1992
+ //! Copy constructor. The newly initialized B+ tree object will contain a
1993
+ //! copy of all key/data pairs.
1994
+ BTree(const BTree& other)
1995
+ : root_(nullptr),
1996
+ head_leaf_(nullptr),
1997
+ tail_leaf_(nullptr),
1998
+ stats_(other.stats_),
1999
+ key_less_(other.key_comp()),
2000
+ allocator_(other.get_allocator())
2001
+ {
2002
+ if (size() > 0)
2003
+ {
2004
+ stats_.leaves = stats_.inner_nodes = 0;
2005
+ if (other.root_)
2006
+ {
2007
+ root_ = copy_recursive(other.root_);
2008
+ }
2009
+ if (self_verify)
2010
+ verify();
2011
+ }
2012
+ }
2013
+
2014
+ private:
2015
+ //! Recursively copy nodes from another B+ tree object
2016
+ struct node* copy_recursive(const node* n)
2017
+ {
2018
+ if (n->is_leafnode())
2019
+ {
2020
+ const LeafNode* leaf = static_cast<const LeafNode*>(n);
2021
+ LeafNode* newleaf = allocate_leaf();
2022
+
2023
+ newleaf->slotuse = leaf->slotuse;
2024
+ std::copy(leaf->slotdata, leaf->slotdata + leaf->slotuse,
2025
+ newleaf->slotdata);
2026
+
2027
+ if (head_leaf_ == nullptr)
2028
+ {
2029
+ head_leaf_ = tail_leaf_ = newleaf;
2030
+ newleaf->prev_leaf = newleaf->next_leaf = nullptr;
2031
+ }
2032
+ else
2033
+ {
2034
+ newleaf->prev_leaf = tail_leaf_;
2035
+ tail_leaf_->next_leaf = newleaf;
2036
+ tail_leaf_ = newleaf;
2037
+ }
2038
+
2039
+ return newleaf;
2040
+ }
2041
+
2042
+ const InnerNode* inner = static_cast<const InnerNode*>(n);
2043
+ InnerNode* newinner = allocate_inner(inner->level);
2044
+
2045
+ newinner->slotuse = inner->slotuse;
2046
+ std::copy(inner->slotkey, inner->slotkey + inner->slotuse,
2047
+ newinner->slotkey);
2048
+
2049
+ for (unsigned short slot = 0; slot <= inner->slotuse; ++slot)
2050
+ newinner->childid[slot] = copy_recursive(inner->childid[slot]);
2051
+
2052
+ return newinner;
2053
+ }
2054
+
2055
+ //! \}
2056
+
2057
+ public:
2058
+ //! \name Public Insertion Functions
2059
+ //! \{
2060
+
2061
+ //! Attempt to insert a key/data pair into the B+ tree. If the tree does not
2062
+ //! allow duplicate keys, then the insert may fail if it is already present.
2063
+ std::pair<iterator, bool> insert(const value_type& x)
2064
+ {
2065
+ return insert_start(key_of_value::get(x), x);
2066
+ }
2067
+
2068
+ //! Attempt to insert a key/data pair into the B+ tree. The iterator hint is
2069
+ //! currently ignored by the B+ tree insertion routine.
2070
+ iterator insert(iterator /* hint */, const value_type& x)
2071
+ {
2072
+ return insert_start(key_of_value::get(x), x).first;
2073
+ }
2074
+
2075
+ //! Attempt to insert the range [first,last) of value_type pairs into the B+
2076
+ //! tree. Each key/data pair is inserted individually; to bulk load the
2077
+ //! tree, use a constructor with range.
2078
+ template <typename InputIterator>
2079
+ void insert(InputIterator first, InputIterator last)
2080
+ {
2081
+ InputIterator iter = first;
2082
+ while (iter != last)
2083
+ {
2084
+ insert(*iter);
2085
+ ++iter;
2086
+ }
2087
+ }
2088
+
2089
+ //! \}
2090
+
2091
+ private:
2092
+ //! \name Private Insertion Functions
2093
+ //! \{
2094
+
2095
+ //! Start the insertion descent at the current root and handle root splits.
2096
+ //! Returns true if the item was inserted
2097
+ std::pair<iterator, bool> insert_start(const key_type& key,
2098
+ const value_type& value)
2099
+ {
2100
+ node* newchild = nullptr;
2101
+ key_type newkey = key_type();
2102
+
2103
+ if (root_ == nullptr)
2104
+ {
2105
+ root_ = head_leaf_ = tail_leaf_ = allocate_leaf();
2106
+ }
2107
+
2108
+ std::pair<iterator, bool> r =
2109
+ insert_descend(root_, key, value, &newkey, &newchild);
2110
+
2111
+ if (newchild)
2112
+ {
2113
+ // this only occurs if insert_descend() could not insert the key
2114
+ // into the root node, this mean the root is full and a new root
2115
+ // needs to be created.
2116
+ InnerNode* newroot = allocate_inner(root_->level + 1);
2117
+ newroot->slotkey[0] = newkey;
2118
+
2119
+ newroot->childid[0] = root_;
2120
+ newroot->childid[1] = newchild;
2121
+
2122
+ newroot->slotuse = 1;
2123
+
2124
+ root_ = newroot;
2125
+ }
2126
+
2127
+ // increment size if the item was inserted
2128
+ if (r.second)
2129
+ ++stats_.size;
2130
+
2131
+ #ifdef TLX_BTREE_DEBUG
2132
+ if (debug)
2133
+ print(std::cout);
2134
+ #endif
2135
+
2136
+ if (self_verify)
2137
+ {
2138
+ verify();
2139
+ TLX_BTREE_ASSERT(exists(key));
2140
+ }
2141
+
2142
+ return r;
2143
+ }
2144
+
2145
+ /*!
2146
+ * Insert an item into the B+ tree.
2147
+ *
2148
+ * Descend down the nodes to a leaf, insert the key/data pair in a free
2149
+ * slot. If the node overflows, then it must be split and the new split node
2150
+ * inserted into the parent. Unroll / this splitting up to the root.
2151
+ */
2152
+ std::pair<iterator, bool> insert_descend(node* n, const key_type& key,
2153
+ const value_type& value,
2154
+ key_type* splitkey,
2155
+ node** splitnode)
2156
+ {
2157
+ if (!n->is_leafnode())
2158
+ {
2159
+ InnerNode* inner = static_cast<InnerNode*>(n);
2160
+
2161
+ key_type newkey = key_type();
2162
+ node* newchild = nullptr;
2163
+
2164
+ unsigned short slot = find_lower(inner, key);
2165
+
2166
+ TLX_BTREE_PRINT("BTree::insert_descend into "
2167
+ << inner->childid[slot]);
2168
+
2169
+ std::pair<iterator, bool> r = insert_descend(
2170
+ inner->childid[slot], key, value, &newkey, &newchild);
2171
+
2172
+ if (newchild)
2173
+ {
2174
+ TLX_BTREE_PRINT("BTree::insert_descend newchild"
2175
+ << " with key " << newkey << " node "
2176
+ << newchild << " at slot " << slot);
2177
+
2178
+ if (inner->is_full())
2179
+ {
2180
+ split_inner_node(inner, splitkey, splitnode, slot);
2181
+
2182
+ TLX_BTREE_PRINT("BTree::insert_descend done split_inner:"
2183
+ << " putslot: " << slot << " putkey: "
2184
+ << newkey << " upkey: " << *splitkey);
2185
+
2186
+ #ifdef TLX_BTREE_DEBUG
2187
+ if (debug)
2188
+ {
2189
+ print_node(std::cout, inner);
2190
+ print_node(std::cout, *splitnode);
2191
+ }
2192
+ #endif
2193
+
2194
+ // check if insert slot is in the split sibling node
2195
+ TLX_BTREE_PRINT("BTree::insert_descend switch: "
2196
+ << slot << " > " << inner->slotuse + 1);
2197
+
2198
+ if (slot == inner->slotuse + 1 &&
2199
+ inner->slotuse < (*splitnode)->slotuse)
2200
+ {
2201
+ // special case when the insert slot matches the split
2202
+ // place between the two nodes, then the insert key
2203
+ // becomes the split key.
2204
+
2205
+ TLX_BTREE_ASSERT(inner->slotuse + 1 < inner_slotmax);
2206
+
2207
+ InnerNode* split = static_cast<InnerNode*>(*splitnode);
2208
+
2209
+ // move the split key and it's datum into the left node
2210
+ inner->slotkey[inner->slotuse] = *splitkey;
2211
+ inner->childid[inner->slotuse + 1] = split->childid[0];
2212
+ inner->slotuse++;
2213
+
2214
+ // set new split key and move corresponding datum into
2215
+ // right node
2216
+ split->childid[0] = newchild;
2217
+ *splitkey = newkey;
2218
+
2219
+ return r;
2220
+ }
2221
+
2222
+ if (slot >= inner->slotuse + 1)
2223
+ {
2224
+ // in case the insert slot is in the newly create split
2225
+ // node, we reuse the code below.
2226
+
2227
+ slot -= inner->slotuse + 1;
2228
+ inner = static_cast<InnerNode*>(*splitnode);
2229
+ TLX_BTREE_PRINT("BTree::insert_descend switching to "
2230
+ "splitted node "
2231
+ << inner << " slot " << slot);
2232
+ }
2233
+ }
2234
+
2235
+ // move items and put pointer to child node into correct slot
2236
+ TLX_BTREE_ASSERT(slot >= 0 && slot <= inner->slotuse);
2237
+
2238
+ std::copy_backward(inner->slotkey + slot,
2239
+ inner->slotkey + inner->slotuse,
2240
+ inner->slotkey + inner->slotuse + 1);
2241
+ std::copy_backward(inner->childid + slot,
2242
+ inner->childid + inner->slotuse + 1,
2243
+ inner->childid + inner->slotuse + 2);
2244
+
2245
+ inner->slotkey[slot] = newkey;
2246
+ inner->childid[slot + 1] = newchild;
2247
+ inner->slotuse++;
2248
+ }
2249
+
2250
+ return r;
2251
+ }
2252
+
2253
+ // n->is_leafnode() == true
2254
+ LeafNode* leaf = static_cast<LeafNode*>(n);
2255
+
2256
+ unsigned short slot = find_lower(leaf, key);
2257
+
2258
+ if (!allow_duplicates && slot < leaf->slotuse &&
2259
+ key_equal(key, leaf->key(slot)))
2260
+ {
2261
+ return std::pair<iterator, bool>(iterator(leaf, slot), false);
2262
+ }
2263
+
2264
+ if (leaf->is_full())
2265
+ {
2266
+ split_leaf_node(leaf, splitkey, splitnode);
2267
+
2268
+ // check if insert slot is in the split sibling node
2269
+ if (slot >= leaf->slotuse)
2270
+ {
2271
+ slot -= leaf->slotuse;
2272
+ leaf = static_cast<LeafNode*>(*splitnode);
2273
+ }
2274
+ }
2275
+
2276
+ // move items and put data item into correct data slot
2277
+ TLX_BTREE_ASSERT(slot >= 0 && slot <= leaf->slotuse);
2278
+
2279
+ std::copy_backward(leaf->slotdata + slot,
2280
+ leaf->slotdata + leaf->slotuse,
2281
+ leaf->slotdata + leaf->slotuse + 1);
2282
+
2283
+ leaf->slotdata[slot] = value;
2284
+ leaf->slotuse++;
2285
+
2286
+ if (splitnode && leaf != *splitnode && slot == leaf->slotuse - 1)
2287
+ {
2288
+ // special case: the node was split, and the insert is at the
2289
+ // last slot of the old node. then the splitkey must be updated.
2290
+ *splitkey = key;
2291
+ }
2292
+
2293
+ return std::pair<iterator, bool>(iterator(leaf, slot), true);
2294
+ }
2295
+
2296
+ //! Split up a leaf node into two equally-filled sibling leaves. Returns the
2297
+ //! new nodes and it's insertion key in the two parameters.
2298
+ void split_leaf_node(LeafNode* leaf, key_type* out_newkey,
2299
+ node** out_newleaf)
2300
+ {
2301
+ TLX_BTREE_ASSERT(leaf->is_full());
2302
+
2303
+ unsigned short mid = (leaf->slotuse >> 1);
2304
+
2305
+ TLX_BTREE_PRINT("BTree::split_leaf_node on " << leaf);
2306
+
2307
+ LeafNode* newleaf = allocate_leaf();
2308
+
2309
+ newleaf->slotuse = leaf->slotuse - mid;
2310
+
2311
+ newleaf->next_leaf = leaf->next_leaf;
2312
+ if (newleaf->next_leaf == nullptr)
2313
+ {
2314
+ TLX_BTREE_ASSERT(leaf == tail_leaf_);
2315
+ tail_leaf_ = newleaf;
2316
+ }
2317
+ else
2318
+ {
2319
+ newleaf->next_leaf->prev_leaf = newleaf;
2320
+ }
2321
+
2322
+ std::copy(leaf->slotdata + mid, leaf->slotdata + leaf->slotuse,
2323
+ newleaf->slotdata);
2324
+
2325
+ leaf->slotuse = mid;
2326
+ leaf->next_leaf = newleaf;
2327
+ newleaf->prev_leaf = leaf;
2328
+
2329
+ *out_newkey = leaf->key(leaf->slotuse - 1);
2330
+ *out_newleaf = newleaf;
2331
+ }
2332
+
2333
+ //! Split up an inner node into two equally-filled sibling nodes. Returns
2334
+ //! the new nodes and it's insertion key in the two parameters. Requires the
2335
+ //! slot of the item will be inserted, so the nodes will be the same size
2336
+ //! after the insert.
2337
+ void split_inner_node(InnerNode* inner, key_type* out_newkey,
2338
+ node** out_newinner, unsigned int addslot)
2339
+ {
2340
+ TLX_BTREE_ASSERT(inner->is_full());
2341
+
2342
+ unsigned short mid = (inner->slotuse >> 1);
2343
+
2344
+ TLX_BTREE_PRINT("BTree::split_inner: mid " << mid << " addslot "
2345
+ << addslot);
2346
+
2347
+ // if the split is uneven and the overflowing item will be put into the
2348
+ // larger node, then the smaller split node may underflow
2349
+ if (addslot <= mid && mid > inner->slotuse - (mid + 1))
2350
+ mid--;
2351
+
2352
+ TLX_BTREE_PRINT("BTree::split_inner: mid " << mid << " addslot "
2353
+ << addslot);
2354
+
2355
+ TLX_BTREE_PRINT("BTree::split_inner_node on "
2356
+ << inner << " into two nodes " << mid << " and "
2357
+ << inner->slotuse - (mid + 1) << " sized");
2358
+
2359
+ InnerNode* newinner = allocate_inner(inner->level);
2360
+
2361
+ newinner->slotuse = inner->slotuse - (mid + 1);
2362
+
2363
+ std::copy(inner->slotkey + mid + 1, inner->slotkey + inner->slotuse,
2364
+ newinner->slotkey);
2365
+ std::copy(inner->childid + mid + 1, inner->childid + inner->slotuse + 1,
2366
+ newinner->childid);
2367
+
2368
+ inner->slotuse = mid;
2369
+
2370
+ *out_newkey = inner->key(mid);
2371
+ *out_newinner = newinner;
2372
+ }
2373
+
2374
+ //! \}
2375
+
2376
+ public:
2377
+ //! \name Bulk Loader - Construct Tree from Sorted Sequence
2378
+ //! \{
2379
+
2380
+ //! Bulk load a sorted range. Loads items into leaves and constructs a
2381
+ //! B-tree above them. The tree must be empty when calling this function.
2382
+ template <typename Iterator>
2383
+ void bulk_load(Iterator ibegin, Iterator iend)
2384
+ {
2385
+ TLX_BTREE_ASSERT(empty());
2386
+
2387
+ stats_.size = iend - ibegin;
2388
+
2389
+ // calculate number of leaves needed, round up.
2390
+ size_t num_items = iend - ibegin;
2391
+ size_t num_leaves = (num_items + leaf_slotmax - 1) / leaf_slotmax;
2392
+
2393
+ TLX_BTREE_PRINT("BTree::bulk_load, level 0: "
2394
+ << stats_.size << " items into " << num_leaves
2395
+ << " leaves with up to "
2396
+ << ((iend - ibegin + num_leaves - 1) / num_leaves)
2397
+ << " items per leaf.");
2398
+
2399
+ Iterator it = ibegin;
2400
+ for (size_t i = 0; i < num_leaves; ++i)
2401
+ {
2402
+ // allocate new leaf node
2403
+ LeafNode* leaf = allocate_leaf();
2404
+
2405
+ // copy keys or (key,value) pairs into leaf nodes, uses template
2406
+ // switch leaf->set_slot().
2407
+ leaf->slotuse = static_cast<int>(num_items / (num_leaves - i));
2408
+ for (size_t s = 0; s < leaf->slotuse; ++s, ++it)
2409
+ leaf->set_slot(s, *it);
2410
+
2411
+ if (tail_leaf_ != nullptr)
2412
+ {
2413
+ tail_leaf_->next_leaf = leaf;
2414
+ leaf->prev_leaf = tail_leaf_;
2415
+ }
2416
+ else
2417
+ {
2418
+ head_leaf_ = leaf;
2419
+ }
2420
+ tail_leaf_ = leaf;
2421
+
2422
+ num_items -= leaf->slotuse;
2423
+ }
2424
+
2425
+ TLX_BTREE_ASSERT(it == iend && num_items == 0);
2426
+
2427
+ // if the btree is so small to fit into one leaf, then we're done.
2428
+ if (head_leaf_ == tail_leaf_)
2429
+ {
2430
+ root_ = head_leaf_;
2431
+ return;
2432
+ }
2433
+
2434
+ TLX_BTREE_ASSERT(stats_.leaves == num_leaves);
2435
+
2436
+ // create first level of inner nodes, pointing to the leaves.
2437
+ size_t num_parents =
2438
+ (num_leaves + (inner_slotmax + 1) - 1) / (inner_slotmax + 1);
2439
+
2440
+ TLX_BTREE_PRINT("BTree::bulk_load, level 1: "
2441
+ << num_leaves << " leaves in " << num_parents
2442
+ << " inner nodes with up to "
2443
+ << ((num_leaves + num_parents - 1) / num_parents)
2444
+ << " leaves per inner node.");
2445
+
2446
+ // save inner nodes and maxkey for next level.
2447
+ typedef std::pair<InnerNode*, const key_type*> nextlevel_type;
2448
+ nextlevel_type* nextlevel = new nextlevel_type[num_parents];
2449
+
2450
+ LeafNode* leaf = head_leaf_;
2451
+ for (size_t i = 0; i < num_parents; ++i)
2452
+ {
2453
+ // allocate new inner node at level 1
2454
+ InnerNode* n = allocate_inner(1);
2455
+
2456
+ n->slotuse = static_cast<int>(num_leaves / (num_parents - i));
2457
+ TLX_BTREE_ASSERT(n->slotuse > 0);
2458
+ // this counts keys, but an inner node has keys+1 children.
2459
+ --n->slotuse;
2460
+
2461
+ // copy last key from each leaf and set child
2462
+ for (unsigned short s = 0; s < n->slotuse; ++s)
2463
+ {
2464
+ n->slotkey[s] = leaf->key(leaf->slotuse - 1);
2465
+ n->childid[s] = leaf;
2466
+ leaf = leaf->next_leaf;
2467
+ }
2468
+ n->childid[n->slotuse] = leaf;
2469
+
2470
+ // track max key of any descendant.
2471
+ nextlevel[i].first = n;
2472
+ nextlevel[i].second = &leaf->key(leaf->slotuse - 1);
2473
+
2474
+ leaf = leaf->next_leaf;
2475
+ num_leaves -= n->slotuse + 1;
2476
+ }
2477
+
2478
+ TLX_BTREE_ASSERT(leaf == nullptr && num_leaves == 0);
2479
+
2480
+ // recursively build inner nodes pointing to inner nodes.
2481
+ for (int level = 2; num_parents != 1; ++level)
2482
+ {
2483
+ size_t num_children = num_parents;
2484
+ num_parents =
2485
+ (num_children + (inner_slotmax + 1) - 1) / (inner_slotmax + 1);
2486
+
2487
+ TLX_BTREE_PRINT("BTree::bulk_load, level "
2488
+ << level << ": " << num_children << " children in "
2489
+ << num_parents << " inner nodes with up to "
2490
+ << ((num_children + num_parents - 1) / num_parents)
2491
+ << " children per inner node.");
2492
+
2493
+ size_t inner_index = 0;
2494
+ for (size_t i = 0; i < num_parents; ++i)
2495
+ {
2496
+ // allocate new inner node at level
2497
+ InnerNode* n = allocate_inner(level);
2498
+
2499
+ n->slotuse = static_cast<int>(num_children / (num_parents - i));
2500
+ TLX_BTREE_ASSERT(n->slotuse > 0);
2501
+ // this counts keys, but an inner node has keys+1 children.
2502
+ --n->slotuse;
2503
+
2504
+ // copy children and maxkeys from nextlevel
2505
+ for (unsigned short s = 0; s < n->slotuse; ++s)
2506
+ {
2507
+ n->slotkey[s] = *nextlevel[inner_index].second;
2508
+ n->childid[s] = nextlevel[inner_index].first;
2509
+ ++inner_index;
2510
+ }
2511
+ n->childid[n->slotuse] = nextlevel[inner_index].first;
2512
+
2513
+ // reuse nextlevel array for parents, because we can overwrite
2514
+ // slots we've already consumed.
2515
+ nextlevel[i].first = n;
2516
+ nextlevel[i].second = nextlevel[inner_index].second;
2517
+
2518
+ ++inner_index;
2519
+ num_children -= n->slotuse + 1;
2520
+ }
2521
+
2522
+ TLX_BTREE_ASSERT(num_children == 0);
2523
+ }
2524
+
2525
+ root_ = nextlevel[0].first;
2526
+ delete[] nextlevel;
2527
+
2528
+ if (self_verify)
2529
+ verify();
2530
+ }
2531
+
2532
+ //! \}
2533
+
2534
+ private:
2535
+ //! \name Support Class Encapsulating Deletion Results
2536
+ //! \{
2537
+
2538
+ //! Result flags of recursive deletion.
2539
+ enum result_flags_t
2540
+ {
2541
+ //! Deletion successful and no fix-ups necessary.
2542
+ btree_ok = 0,
2543
+
2544
+ //! Deletion not successful because key was not found.
2545
+ btree_not_found = 1,
2546
+
2547
+ //! Deletion successful, the last key was updated so parent slotkeys
2548
+ //! need updates.
2549
+ btree_update_lastkey = 2,
2550
+
2551
+ //! Deletion successful, children nodes were merged and the parent needs
2552
+ //! to remove the empty node.
2553
+ btree_fixmerge = 4
2554
+ };
2555
+
2556
+ //! B+ tree recursive deletion has much information which is needs to be
2557
+ //! passed upward.
2558
+ struct result_t
2559
+ {
2560
+ //! Merged result flags
2561
+ result_flags_t flags;
2562
+
2563
+ //! The key to be updated at the parent's slot
2564
+ key_type lastkey;
2565
+
2566
+ //! Constructor of a result with a specific flag, this can also be used
2567
+ //! as for implicit conversion.
2568
+ result_t(result_flags_t f = btree_ok) : flags(f), lastkey()
2569
+ {
2570
+ }
2571
+
2572
+ //! Constructor with a lastkey value.
2573
+ result_t(result_flags_t f, const key_type& k) : flags(f), lastkey(k)
2574
+ {
2575
+ }
2576
+
2577
+ //! Test if this result object has a given flag set.
2578
+ bool has(result_flags_t f) const
2579
+ {
2580
+ return (flags & f) != 0;
2581
+ }
2582
+
2583
+ //! Merge two results OR-ing the result flags and overwriting lastkeys.
2584
+ result_t& operator|=(const result_t& other)
2585
+ {
2586
+ flags = result_flags_t(flags | other.flags);
2587
+
2588
+ // we overwrite existing lastkeys on purpose
2589
+ if (other.has(btree_update_lastkey))
2590
+ lastkey = other.lastkey;
2591
+
2592
+ return *this;
2593
+ }
2594
+ };
2595
+
2596
+ //! \}
2597
+
2598
+ public:
2599
+ //! \name Public Erase Functions
2600
+ //! \{
2601
+
2602
+ //! Erases one (the first) of the key/data pairs associated with the given
2603
+ //! key.
2604
+ bool erase_one(const key_type& key)
2605
+ {
2606
+ TLX_BTREE_PRINT("BTree::erase_one(" << key << ") on btree size "
2607
+ << size());
2608
+
2609
+ if (self_verify)
2610
+ verify();
2611
+
2612
+ if (!root_)
2613
+ return false;
2614
+
2615
+ result_t result = erase_one_descend(key, root_, nullptr, nullptr,
2616
+ nullptr, nullptr, nullptr, 0);
2617
+
2618
+ if (!result.has(btree_not_found))
2619
+ --stats_.size;
2620
+
2621
+ #ifdef TLX_BTREE_DEBUG
2622
+ if (debug)
2623
+ print(std::cout);
2624
+ #endif
2625
+ if (self_verify)
2626
+ verify();
2627
+
2628
+ return !result.has(btree_not_found);
2629
+ }
2630
+
2631
+ //! Erases all the key/data pairs associated with the given key. This is
2632
+ //! implemented using erase_one().
2633
+ size_type erase(const key_type& key)
2634
+ {
2635
+ size_type c = 0;
2636
+
2637
+ while (erase_one(key))
2638
+ {
2639
+ ++c;
2640
+ if (!allow_duplicates)
2641
+ break;
2642
+ }
2643
+
2644
+ return c;
2645
+ }
2646
+
2647
+ //! Erase the key/data pair referenced by the iterator.
2648
+ void erase(iterator iter)
2649
+ {
2650
+ TLX_BTREE_PRINT("BTree::erase_iter(" << iter.curr_leaf << ","
2651
+ << iter.curr_slot
2652
+ << ") on btree size " << size());
2653
+
2654
+ if (self_verify)
2655
+ verify();
2656
+
2657
+ if (!root_)
2658
+ return;
2659
+
2660
+ result_t result = erase_iter_descend(iter, root_, nullptr, nullptr,
2661
+ nullptr, nullptr, nullptr, 0);
2662
+
2663
+ if (!result.has(btree_not_found))
2664
+ --stats_.size;
2665
+
2666
+ #ifdef TLX_BTREE_DEBUG
2667
+ if (debug)
2668
+ print(std::cout);
2669
+ #endif
2670
+ if (self_verify)
2671
+ verify();
2672
+ }
2673
+
2674
+ #ifdef BTREE_TODO
2675
+ //! Erase all key/data pairs in the range [first,last). This function is
2676
+ //! currently not implemented by the B+ Tree.
2677
+ void erase(iterator /* first */, iterator /* last */)
2678
+ {
2679
+ abort();
2680
+ }
2681
+ #endif
2682
+
2683
+ //! \}
2684
+
2685
+ private:
2686
+ //! \name Private Erase Functions
2687
+ //! \{
2688
+
2689
+ /*!
2690
+ * Erase one (the first) key/data pair in the B+ tree matching key.
2691
+ *
2692
+ * Descends down the tree in search of key. During the descent the parent,
2693
+ * left and right siblings and their parents are computed and passed
2694
+ * down. Once the key/data pair is found, it is removed from the leaf. If
2695
+ * the leaf underflows 6 different cases are handled. These cases resolve
2696
+ * the underflow by shifting key/data pairs from adjacent sibling nodes,
2697
+ * merging two sibling nodes or trimming the tree.
2698
+ */
2699
+ result_t erase_one_descend(const key_type& key, node* curr, node* left,
2700
+ node* right, InnerNode* left_parent,
2701
+ InnerNode* right_parent, InnerNode* parent,
2702
+ unsigned int parentslot)
2703
+ {
2704
+ if (curr->is_leafnode())
2705
+ {
2706
+ LeafNode* leaf = static_cast<LeafNode*>(curr);
2707
+ LeafNode* left_leaf = static_cast<LeafNode*>(left);
2708
+ LeafNode* right_leaf = static_cast<LeafNode*>(right);
2709
+
2710
+ unsigned short slot = find_lower(leaf, key);
2711
+
2712
+ if (slot >= leaf->slotuse || !key_equal(key, leaf->key(slot)))
2713
+ {
2714
+ TLX_BTREE_PRINT("Could not find key " << key << " to erase.");
2715
+
2716
+ return btree_not_found;
2717
+ }
2718
+
2719
+ TLX_BTREE_PRINT("Found key in leaf " << curr << " at slot "
2720
+ << slot);
2721
+
2722
+ std::copy(leaf->slotdata + slot + 1, leaf->slotdata + leaf->slotuse,
2723
+ leaf->slotdata + slot);
2724
+
2725
+ leaf->slotuse--;
2726
+
2727
+ result_t myres = btree_ok;
2728
+
2729
+ // if the last key of the leaf was changed, the parent is notified
2730
+ // and updates the key of this leaf
2731
+ if (slot == leaf->slotuse)
2732
+ {
2733
+ if (parent && parentslot < parent->slotuse)
2734
+ {
2735
+ TLX_BTREE_ASSERT(parent->childid[parentslot] == curr);
2736
+ parent->slotkey[parentslot] = leaf->key(leaf->slotuse - 1);
2737
+ }
2738
+ else
2739
+ {
2740
+ if (leaf->slotuse >= 1)
2741
+ {
2742
+ TLX_BTREE_PRINT("Scheduling lastkeyupdate: key "
2743
+ << leaf->key(leaf->slotuse - 1));
2744
+ myres |= result_t(btree_update_lastkey,
2745
+ leaf->key(leaf->slotuse - 1));
2746
+ }
2747
+ else
2748
+ {
2749
+ TLX_BTREE_ASSERT(leaf == root_);
2750
+ }
2751
+ }
2752
+ }
2753
+
2754
+ if (leaf->is_underflow() && !(leaf == root_ && leaf->slotuse >= 1))
2755
+ {
2756
+ // determine what to do about the underflow
2757
+
2758
+ // case : if this empty leaf is the root, then delete all nodes
2759
+ // and set root to nullptr.
2760
+ if (left_leaf == nullptr && right_leaf == nullptr)
2761
+ {
2762
+ TLX_BTREE_ASSERT(leaf == root_);
2763
+ TLX_BTREE_ASSERT(leaf->slotuse == 0);
2764
+
2765
+ free_node(root_);
2766
+
2767
+ root_ = leaf = nullptr;
2768
+ head_leaf_ = tail_leaf_ = nullptr;
2769
+
2770
+ // will be decremented soon by insert_start()
2771
+ TLX_BTREE_ASSERT(stats_.size == 1);
2772
+ TLX_BTREE_ASSERT(stats_.leaves == 0);
2773
+ TLX_BTREE_ASSERT(stats_.inner_nodes == 0);
2774
+
2775
+ return btree_ok;
2776
+ }
2777
+ // case : if both left and right leaves would underflow in case
2778
+ // of a shift, then merging is necessary. choose the more local
2779
+ // merger with our parent
2780
+ if ((left_leaf == nullptr || left_leaf->is_few()) &&
2781
+ (right_leaf == nullptr || right_leaf->is_few()))
2782
+ {
2783
+ if (left_parent == parent)
2784
+ myres |= merge_leaves(left_leaf, leaf, left_parent);
2785
+ else
2786
+ myres |= merge_leaves(leaf, right_leaf, right_parent);
2787
+ }
2788
+ // case : the right leaf has extra data, so balance right with
2789
+ // current
2790
+ else if ((left_leaf != nullptr && left_leaf->is_few()) &&
2791
+ (right_leaf != nullptr && !right_leaf->is_few()))
2792
+ {
2793
+ if (right_parent == parent)
2794
+ myres |= shift_left_leaf(leaf, right_leaf, right_parent,
2795
+ parentslot);
2796
+ else
2797
+ myres |= merge_leaves(left_leaf, leaf, left_parent);
2798
+ }
2799
+ // case : the left leaf has extra data, so balance left with
2800
+ // current
2801
+ else if ((left_leaf != nullptr && !left_leaf->is_few()) &&
2802
+ (right_leaf != nullptr && right_leaf->is_few()))
2803
+ {
2804
+ if (left_parent == parent)
2805
+ shift_right_leaf(left_leaf, leaf, left_parent,
2806
+ parentslot - 1);
2807
+ else
2808
+ myres |= merge_leaves(leaf, right_leaf, right_parent);
2809
+ }
2810
+ // case : both the leaf and right leaves have extra data and our
2811
+ // parent, choose the leaf with more data
2812
+ else if (left_parent == right_parent)
2813
+ {
2814
+ if (left_leaf->slotuse <= right_leaf->slotuse)
2815
+ myres |= shift_left_leaf(leaf, right_leaf, right_parent,
2816
+ parentslot);
2817
+ else
2818
+ shift_right_leaf(left_leaf, leaf, left_parent,
2819
+ parentslot - 1);
2820
+ }
2821
+ else
2822
+ {
2823
+ if (left_parent == parent)
2824
+ shift_right_leaf(left_leaf, leaf, left_parent,
2825
+ parentslot - 1);
2826
+ else
2827
+ myres |= shift_left_leaf(leaf, right_leaf, right_parent,
2828
+ parentslot);
2829
+ }
2830
+ }
2831
+
2832
+ return myres;
2833
+ }
2834
+
2835
+ // !curr->is_leafnode()
2836
+ InnerNode* inner = static_cast<InnerNode*>(curr);
2837
+ InnerNode* left_inner = static_cast<InnerNode*>(left);
2838
+ InnerNode* right_inner = static_cast<InnerNode*>(right);
2839
+
2840
+ node *myleft, *myright;
2841
+ InnerNode *myleft_parent, *myright_parent;
2842
+
2843
+ unsigned short slot = find_lower(inner, key);
2844
+
2845
+ if (slot == 0)
2846
+ {
2847
+ myleft =
2848
+ (left == nullptr) ?
2849
+ nullptr :
2850
+ static_cast<InnerNode*>(left)->childid[left->slotuse - 1];
2851
+ myleft_parent = left_parent;
2852
+ }
2853
+ else
2854
+ {
2855
+ myleft = inner->childid[slot - 1];
2856
+ myleft_parent = inner;
2857
+ }
2858
+
2859
+ if (slot == inner->slotuse)
2860
+ {
2861
+ myright = (right == nullptr) ?
2862
+ nullptr :
2863
+ static_cast<InnerNode*>(right)->childid[0];
2864
+ myright_parent = right_parent;
2865
+ }
2866
+ else
2867
+ {
2868
+ myright = inner->childid[slot + 1];
2869
+ myright_parent = inner;
2870
+ }
2871
+
2872
+ TLX_BTREE_PRINT("erase_one_descend into " << inner->childid[slot]);
2873
+
2874
+ result_t result =
2875
+ erase_one_descend(key, inner->childid[slot], myleft, myright,
2876
+ myleft_parent, myright_parent, inner, slot);
2877
+
2878
+ result_t myres = btree_ok;
2879
+
2880
+ if (result.has(btree_not_found))
2881
+ {
2882
+ return result;
2883
+ }
2884
+
2885
+ if (result.has(btree_update_lastkey))
2886
+ {
2887
+ if (parent && parentslot < parent->slotuse)
2888
+ {
2889
+ TLX_BTREE_PRINT("Fixing lastkeyupdate: key "
2890
+ << result.lastkey << " into parent " << parent
2891
+ << " at parentslot " << parentslot);
2892
+
2893
+ TLX_BTREE_ASSERT(parent->childid[parentslot] == curr);
2894
+ parent->slotkey[parentslot] = result.lastkey;
2895
+ }
2896
+ else
2897
+ {
2898
+ TLX_BTREE_PRINT("Forwarding lastkeyupdate: key "
2899
+ << result.lastkey);
2900
+ myres |= result_t(btree_update_lastkey, result.lastkey);
2901
+ }
2902
+ }
2903
+
2904
+ if (result.has(btree_fixmerge))
2905
+ {
2906
+ // either the current node or the next is empty and should be
2907
+ // removed
2908
+ if (inner->childid[slot]->slotuse != 0)
2909
+ slot++;
2910
+
2911
+ // this is the child slot invalidated by the merge
2912
+ TLX_BTREE_ASSERT(inner->childid[slot]->slotuse == 0);
2913
+
2914
+ free_node(inner->childid[slot]);
2915
+
2916
+ std::copy(inner->slotkey + slot, inner->slotkey + inner->slotuse,
2917
+ inner->slotkey + slot - 1);
2918
+ std::copy(inner->childid + slot + 1,
2919
+ inner->childid + inner->slotuse + 1,
2920
+ inner->childid + slot);
2921
+
2922
+ inner->slotuse--;
2923
+
2924
+ if (inner->level == 1)
2925
+ {
2926
+ // fix split key for children leaves
2927
+ slot--;
2928
+ LeafNode* child = static_cast<LeafNode*>(inner->childid[slot]);
2929
+ inner->slotkey[slot] = child->key(child->slotuse - 1);
2930
+ }
2931
+ }
2932
+
2933
+ if (inner->is_underflow() && !(inner == root_ && inner->slotuse >= 1))
2934
+ {
2935
+ // case: the inner node is the root and has just one child. that
2936
+ // child becomes the new root
2937
+ if (left_inner == nullptr && right_inner == nullptr)
2938
+ {
2939
+ TLX_BTREE_ASSERT(inner == root_);
2940
+ TLX_BTREE_ASSERT(inner->slotuse == 0);
2941
+
2942
+ root_ = inner->childid[0];
2943
+
2944
+ inner->slotuse = 0;
2945
+ free_node(inner);
2946
+
2947
+ return btree_ok;
2948
+ }
2949
+ // case : if both left and right leaves would underflow in case
2950
+ // of a shift, then merging is necessary. choose the more local
2951
+ // merger with our parent
2952
+ if ((left_inner == nullptr || left_inner->is_few()) &&
2953
+ (right_inner == nullptr || right_inner->is_few()))
2954
+ {
2955
+ if (left_parent == parent)
2956
+ myres |= merge_inner(left_inner, inner, left_parent,
2957
+ parentslot - 1);
2958
+ else
2959
+ myres |= merge_inner(inner, right_inner, right_parent,
2960
+ parentslot);
2961
+ }
2962
+ // case : the right leaf has extra data, so balance right with
2963
+ // current
2964
+ else if ((left_inner != nullptr && left_inner->is_few()) &&
2965
+ (right_inner != nullptr && !right_inner->is_few()))
2966
+ {
2967
+ if (right_parent == parent)
2968
+ shift_left_inner(inner, right_inner, right_parent,
2969
+ parentslot);
2970
+ else
2971
+ myres |= merge_inner(left_inner, inner, left_parent,
2972
+ parentslot - 1);
2973
+ }
2974
+ // case : the left leaf has extra data, so balance left with
2975
+ // current
2976
+ else if ((left_inner != nullptr && !left_inner->is_few()) &&
2977
+ (right_inner != nullptr && right_inner->is_few()))
2978
+ {
2979
+ if (left_parent == parent)
2980
+ shift_right_inner(left_inner, inner, left_parent,
2981
+ parentslot - 1);
2982
+ else
2983
+ myres |= merge_inner(inner, right_inner, right_parent,
2984
+ parentslot);
2985
+ }
2986
+ // case : both the leaf and right leaves have extra data and our
2987
+ // parent, choose the leaf with more data
2988
+ else if (left_parent == right_parent)
2989
+ {
2990
+ if (left_inner->slotuse <= right_inner->slotuse)
2991
+ shift_left_inner(inner, right_inner, right_parent,
2992
+ parentslot);
2993
+ else
2994
+ shift_right_inner(left_inner, inner, left_parent,
2995
+ parentslot - 1);
2996
+ }
2997
+ else
2998
+ {
2999
+ if (left_parent == parent)
3000
+ shift_right_inner(left_inner, inner, left_parent,
3001
+ parentslot - 1);
3002
+ else
3003
+ shift_left_inner(inner, right_inner, right_parent,
3004
+ parentslot);
3005
+ }
3006
+ }
3007
+
3008
+ return myres;
3009
+ }
3010
+
3011
+ /*!
3012
+ * Erase one key/data pair referenced by an iterator in the B+ tree.
3013
+ *
3014
+ * Descends down the tree in search of an iterator. During the descent the
3015
+ * parent, left and right siblings and their parents are computed and passed
3016
+ * down. The difficulty is that the iterator contains only a pointer to a
3017
+ * LeafNode, which means that this function must do a recursive depth first
3018
+ * search for that leaf node in the subtree containing all pairs of the same
3019
+ * key. This subtree can be very large, even the whole tree, though in
3020
+ * practice it would not make sense to have so many duplicate keys.
3021
+ *
3022
+ * Once the referenced key/data pair is found, it is removed from the leaf
3023
+ * and the same underflow cases are handled as in erase_one_descend.
3024
+ */
3025
+ result_t erase_iter_descend(const iterator& iter, node* curr, node* left,
3026
+ node* right, InnerNode* left_parent,
3027
+ InnerNode* right_parent, InnerNode* parent,
3028
+ unsigned int parentslot)
3029
+ {
3030
+ if (curr->is_leafnode())
3031
+ {
3032
+ LeafNode* leaf = static_cast<LeafNode*>(curr);
3033
+ LeafNode* left_leaf = static_cast<LeafNode*>(left);
3034
+ LeafNode* right_leaf = static_cast<LeafNode*>(right);
3035
+
3036
+ // if this is not the correct leaf, get next step in recursive
3037
+ // search
3038
+ if (leaf != iter.curr_leaf)
3039
+ {
3040
+ return btree_not_found;
3041
+ }
3042
+
3043
+ if (iter.curr_slot >= leaf->slotuse)
3044
+ {
3045
+ TLX_BTREE_PRINT("Could not find iterator ("
3046
+ << iter.curr_leaf << "," << iter.curr_slot
3047
+ << ") to erase. Invalid leaf node?");
3048
+
3049
+ return btree_not_found;
3050
+ }
3051
+
3052
+ unsigned short slot = iter.curr_slot;
3053
+
3054
+ TLX_BTREE_PRINT("Found iterator in leaf " << curr << " at slot "
3055
+ << slot);
3056
+
3057
+ std::copy(leaf->slotdata + slot + 1, leaf->slotdata + leaf->slotuse,
3058
+ leaf->slotdata + slot);
3059
+
3060
+ leaf->slotuse--;
3061
+
3062
+ result_t myres = btree_ok;
3063
+
3064
+ // if the last key of the leaf was changed, the parent is notified
3065
+ // and updates the key of this leaf
3066
+ if (slot == leaf->slotuse)
3067
+ {
3068
+ if (parent && parentslot < parent->slotuse)
3069
+ {
3070
+ TLX_BTREE_ASSERT(parent->childid[parentslot] == curr);
3071
+ parent->slotkey[parentslot] = leaf->key(leaf->slotuse - 1);
3072
+ }
3073
+ else
3074
+ {
3075
+ if (leaf->slotuse >= 1)
3076
+ {
3077
+ TLX_BTREE_PRINT("Scheduling lastkeyupdate: key "
3078
+ << leaf->key(leaf->slotuse - 1));
3079
+ myres |= result_t(btree_update_lastkey,
3080
+ leaf->key(leaf->slotuse - 1));
3081
+ }
3082
+ else
3083
+ {
3084
+ TLX_BTREE_ASSERT(leaf == root_);
3085
+ }
3086
+ }
3087
+ }
3088
+
3089
+ if (leaf->is_underflow() && !(leaf == root_ && leaf->slotuse >= 1))
3090
+ {
3091
+ // determine what to do about the underflow
3092
+
3093
+ // case : if this empty leaf is the root, then delete all nodes
3094
+ // and set root to nullptr.
3095
+ if (left_leaf == nullptr && right_leaf == nullptr)
3096
+ {
3097
+ TLX_BTREE_ASSERT(leaf == root_);
3098
+ TLX_BTREE_ASSERT(leaf->slotuse == 0);
3099
+
3100
+ free_node(root_);
3101
+
3102
+ root_ = leaf = nullptr;
3103
+ head_leaf_ = tail_leaf_ = nullptr;
3104
+
3105
+ // will be decremented soon by insert_start()
3106
+ TLX_BTREE_ASSERT(stats_.size == 1);
3107
+ TLX_BTREE_ASSERT(stats_.leaves == 0);
3108
+ TLX_BTREE_ASSERT(stats_.inner_nodes == 0);
3109
+
3110
+ return btree_ok;
3111
+ }
3112
+ // case : if both left and right leaves would underflow in case
3113
+ // of a shift, then merging is necessary. choose the more local
3114
+ // merger with our parent
3115
+ if ((left_leaf == nullptr || left_leaf->is_few()) &&
3116
+ (right_leaf == nullptr || right_leaf->is_few()))
3117
+ {
3118
+ if (left_parent == parent)
3119
+ myres |= merge_leaves(left_leaf, leaf, left_parent);
3120
+ else
3121
+ myres |= merge_leaves(leaf, right_leaf, right_parent);
3122
+ }
3123
+ // case : the right leaf has extra data, so balance right with
3124
+ // current
3125
+ else if ((left_leaf != nullptr && left_leaf->is_few()) &&
3126
+ (right_leaf != nullptr && !right_leaf->is_few()))
3127
+ {
3128
+ if (right_parent == parent)
3129
+ {
3130
+ myres |= shift_left_leaf(leaf, right_leaf, right_parent,
3131
+ parentslot);
3132
+ }
3133
+ else
3134
+ {
3135
+ myres |= merge_leaves(left_leaf, leaf, left_parent);
3136
+ }
3137
+ }
3138
+ // case : the left leaf has extra data, so balance left with
3139
+ // current
3140
+ else if ((left_leaf != nullptr && !left_leaf->is_few()) &&
3141
+ (right_leaf != nullptr && right_leaf->is_few()))
3142
+ {
3143
+ if (left_parent == parent)
3144
+ {
3145
+ shift_right_leaf(left_leaf, leaf, left_parent,
3146
+ parentslot - 1);
3147
+ }
3148
+ else
3149
+ {
3150
+ myres |= merge_leaves(leaf, right_leaf, right_parent);
3151
+ }
3152
+ }
3153
+ // case : both the leaf and right leaves have extra data and our
3154
+ // parent, choose the leaf with more data
3155
+ else if (left_parent == right_parent)
3156
+ {
3157
+ if (left_leaf->slotuse <= right_leaf->slotuse)
3158
+ {
3159
+ myres |= shift_left_leaf(leaf, right_leaf, right_parent,
3160
+ parentslot);
3161
+ }
3162
+ else
3163
+ {
3164
+ shift_right_leaf(left_leaf, leaf, left_parent,
3165
+ parentslot - 1);
3166
+ }
3167
+ }
3168
+ else
3169
+ {
3170
+ if (left_parent == parent)
3171
+ {
3172
+ shift_right_leaf(left_leaf, leaf, left_parent,
3173
+ parentslot - 1);
3174
+ }
3175
+ else
3176
+ {
3177
+ myres |= shift_left_leaf(leaf, right_leaf, right_parent,
3178
+ parentslot);
3179
+ }
3180
+ }
3181
+ }
3182
+
3183
+ return myres;
3184
+ }
3185
+
3186
+ // !curr->is_leafnode()
3187
+ InnerNode* inner = static_cast<InnerNode*>(curr);
3188
+ InnerNode* left_inner = static_cast<InnerNode*>(left);
3189
+ InnerNode* right_inner = static_cast<InnerNode*>(right);
3190
+
3191
+ // find first slot below which the searched iterator might be
3192
+ // located.
3193
+
3194
+ result_t result;
3195
+ unsigned short slot = find_lower(inner, iter.key());
3196
+
3197
+ while (slot <= inner->slotuse)
3198
+ {
3199
+ node *myleft, *myright;
3200
+ InnerNode *myleft_parent, *myright_parent;
3201
+
3202
+ if (slot == 0)
3203
+ {
3204
+ myleft = (left == nullptr) ? nullptr :
3205
+ static_cast<InnerNode*>(left)
3206
+ ->childid[left->slotuse - 1];
3207
+ myleft_parent = left_parent;
3208
+ }
3209
+ else
3210
+ {
3211
+ myleft = inner->childid[slot - 1];
3212
+ myleft_parent = inner;
3213
+ }
3214
+
3215
+ if (slot == inner->slotuse)
3216
+ {
3217
+ myright = (right == nullptr) ?
3218
+ nullptr :
3219
+ static_cast<InnerNode*>(right)->childid[0];
3220
+ myright_parent = right_parent;
3221
+ }
3222
+ else
3223
+ {
3224
+ myright = inner->childid[slot + 1];
3225
+ myright_parent = inner;
3226
+ }
3227
+
3228
+ TLX_BTREE_PRINT("erase_iter_descend into " << inner->childid[slot]);
3229
+
3230
+ result =
3231
+ erase_iter_descend(iter, inner->childid[slot], myleft, myright,
3232
+ myleft_parent, myright_parent, inner, slot);
3233
+
3234
+ if (!result.has(btree_not_found))
3235
+ break;
3236
+
3237
+ // continue recursive search for leaf on next slot
3238
+
3239
+ if (slot < inner->slotuse &&
3240
+ key_less(inner->slotkey[slot], iter.key()))
3241
+ return btree_not_found;
3242
+
3243
+ ++slot;
3244
+ }
3245
+
3246
+ if (slot > inner->slotuse)
3247
+ return btree_not_found;
3248
+
3249
+ result_t myres = btree_ok;
3250
+
3251
+ if (result.has(btree_update_lastkey))
3252
+ {
3253
+ if (parent && parentslot < parent->slotuse)
3254
+ {
3255
+ TLX_BTREE_PRINT("Fixing lastkeyupdate: key "
3256
+ << result.lastkey << " into parent "
3257
+ << parent << " at parentslot "
3258
+ << parentslot);
3259
+
3260
+ TLX_BTREE_ASSERT(parent->childid[parentslot] == curr);
3261
+ parent->slotkey[parentslot] = result.lastkey;
3262
+ }
3263
+ else
3264
+ {
3265
+ TLX_BTREE_PRINT("Forwarding lastkeyupdate: key "
3266
+ << result.lastkey);
3267
+ myres |= result_t(btree_update_lastkey, result.lastkey);
3268
+ }
3269
+ }
3270
+
3271
+ if (result.has(btree_fixmerge))
3272
+ {
3273
+ // either the current node or the next is empty and should be
3274
+ // removed
3275
+ if (inner->childid[slot]->slotuse != 0)
3276
+ slot++;
3277
+
3278
+ // this is the child slot invalidated by the merge
3279
+ TLX_BTREE_ASSERT(inner->childid[slot]->slotuse == 0);
3280
+
3281
+ free_node(inner->childid[slot]);
3282
+
3283
+ std::copy(inner->slotkey + slot,
3284
+ inner->slotkey + inner->slotuse,
3285
+ inner->slotkey + slot - 1);
3286
+ std::copy(inner->childid + slot + 1,
3287
+ inner->childid + inner->slotuse + 1,
3288
+ inner->childid + slot);
3289
+
3290
+ inner->slotuse--;
3291
+
3292
+ if (inner->level == 1)
3293
+ {
3294
+ // fix split key for children leaves
3295
+ slot--;
3296
+ LeafNode* child =
3297
+ static_cast<LeafNode*>(inner->childid[slot]);
3298
+ inner->slotkey[slot] = child->key(child->slotuse - 1);
3299
+ }
3300
+ }
3301
+
3302
+ if (inner->is_underflow() &&
3303
+ !(inner == root_ && inner->slotuse >= 1))
3304
+ {
3305
+ // case: the inner node is the root and has just one
3306
+ // child. that child becomes the new root
3307
+ if (left_inner == nullptr && right_inner == nullptr)
3308
+ {
3309
+ TLX_BTREE_ASSERT(inner == root_);
3310
+ TLX_BTREE_ASSERT(inner->slotuse == 0);
3311
+
3312
+ root_ = inner->childid[0];
3313
+
3314
+ inner->slotuse = 0;
3315
+ free_node(inner);
3316
+
3317
+ return btree_ok;
3318
+ }
3319
+ // case : if both left and right leaves would underflow in case
3320
+ // of a shift, then merging is necessary. choose the more local
3321
+ // merger with our parent
3322
+ if ((left_inner == nullptr || left_inner->is_few()) &&
3323
+ (right_inner == nullptr || right_inner->is_few()))
3324
+ {
3325
+ if (left_parent == parent)
3326
+ {
3327
+ myres |= merge_inner(left_inner, inner, left_parent,
3328
+ parentslot - 1);
3329
+ }
3330
+ else
3331
+ {
3332
+ myres |= merge_inner(inner, right_inner, right_parent,
3333
+ parentslot);
3334
+ }
3335
+ }
3336
+ // case : the right leaf has extra data, so balance right with
3337
+ // current
3338
+ else if ((left_inner != nullptr && left_inner->is_few()) &&
3339
+ (right_inner != nullptr && !right_inner->is_few()))
3340
+ {
3341
+ if (right_parent == parent)
3342
+ {
3343
+ shift_left_inner(inner, right_inner, right_parent,
3344
+ parentslot);
3345
+ }
3346
+ else
3347
+ {
3348
+ myres |= merge_inner(left_inner, inner, left_parent,
3349
+ parentslot - 1);
3350
+ }
3351
+ }
3352
+ // case : the left leaf has extra data, so balance left with
3353
+ // current
3354
+ else if ((left_inner != nullptr && !left_inner->is_few()) &&
3355
+ (right_inner != nullptr && right_inner->is_few()))
3356
+ {
3357
+ if (left_parent == parent)
3358
+ {
3359
+ shift_right_inner(left_inner, inner, left_parent,
3360
+ parentslot - 1);
3361
+ }
3362
+ else
3363
+ {
3364
+ myres |= merge_inner(inner, right_inner, right_parent,
3365
+ parentslot);
3366
+ }
3367
+ }
3368
+ // case : both the leaf and right leaves have extra data and our
3369
+ // parent, choose the leaf with more data
3370
+ else if (left_parent == right_parent)
3371
+ {
3372
+ if (left_inner->slotuse <= right_inner->slotuse)
3373
+ {
3374
+ shift_left_inner(inner, right_inner, right_parent,
3375
+ parentslot);
3376
+ }
3377
+ else
3378
+ {
3379
+ shift_right_inner(left_inner, inner, left_parent,
3380
+ parentslot - 1);
3381
+ }
3382
+ }
3383
+ else
3384
+ {
3385
+ if (left_parent == parent)
3386
+ {
3387
+ shift_right_inner(left_inner, inner, left_parent,
3388
+ parentslot - 1);
3389
+ }
3390
+ else
3391
+ {
3392
+ shift_left_inner(inner, right_inner, right_parent,
3393
+ parentslot);
3394
+ }
3395
+ }
3396
+ }
3397
+
3398
+ return myres;
3399
+ }
3400
+
3401
+ //! Merge two leaf nodes. The function moves all key/data pairs from right
3402
+ //! to left and sets right's slotuse to zero. The right slot is then removed
3403
+ //! by the calling parent node.
3404
+ result_t merge_leaves(LeafNode* left, LeafNode* right, InnerNode* parent)
3405
+ {
3406
+ TLX_BTREE_PRINT("Merge leaf nodes " << left << " and " << right
3407
+ << " with common parent " << parent
3408
+ << ".");
3409
+ (void) parent;
3410
+
3411
+ TLX_BTREE_ASSERT(left->is_leafnode() && right->is_leafnode());
3412
+ TLX_BTREE_ASSERT(parent->level == 1);
3413
+
3414
+ TLX_BTREE_ASSERT(left->slotuse + right->slotuse < leaf_slotmax);
3415
+
3416
+ std::copy(right->slotdata, right->slotdata + right->slotuse,
3417
+ left->slotdata + left->slotuse);
3418
+
3419
+ left->slotuse += right->slotuse;
3420
+
3421
+ left->next_leaf = right->next_leaf;
3422
+ if (left->next_leaf)
3423
+ left->next_leaf->prev_leaf = left;
3424
+ else
3425
+ tail_leaf_ = left;
3426
+
3427
+ right->slotuse = 0;
3428
+
3429
+ return btree_fixmerge;
3430
+ }
3431
+
3432
+ //! Merge two inner nodes. The function moves all key/childid pairs from
3433
+ //! right to left and sets right's slotuse to zero. The right slot is then
3434
+ //! removed by the calling parent node.
3435
+ static result_t merge_inner(InnerNode* left, InnerNode* right,
3436
+ InnerNode* parent, unsigned int parentslot)
3437
+ {
3438
+ TLX_BTREE_PRINT("Merge inner nodes " << left << " and " << right
3439
+ << " with common parent " << parent
3440
+ << ".");
3441
+
3442
+ TLX_BTREE_ASSERT(left->level == right->level);
3443
+ TLX_BTREE_ASSERT(parent->level == left->level + 1);
3444
+
3445
+ TLX_BTREE_ASSERT(parent->childid[parentslot] == left);
3446
+
3447
+ TLX_BTREE_ASSERT(left->slotuse + right->slotuse < inner_slotmax);
3448
+
3449
+ if (self_verify)
3450
+ {
3451
+ // find the left node's slot in the parent's children
3452
+ unsigned int leftslot = 0;
3453
+ while (leftslot <= parent->slotuse &&
3454
+ parent->childid[leftslot] != left)
3455
+ ++leftslot;
3456
+
3457
+ TLX_BTREE_ASSERT(leftslot < parent->slotuse);
3458
+ TLX_BTREE_ASSERT(parent->childid[leftslot] == left);
3459
+ TLX_BTREE_ASSERT(parent->childid[leftslot + 1] == right);
3460
+
3461
+ TLX_BTREE_ASSERT(parentslot == leftslot);
3462
+ }
3463
+
3464
+ // retrieve the decision key from parent
3465
+ left->slotkey[left->slotuse] = parent->slotkey[parentslot];
3466
+ left->slotuse++;
3467
+
3468
+ // copy over keys and children from right
3469
+ std::copy(right->slotkey, right->slotkey + right->slotuse,
3470
+ left->slotkey + left->slotuse);
3471
+ std::copy(right->childid, right->childid + right->slotuse + 1,
3472
+ left->childid + left->slotuse);
3473
+
3474
+ left->slotuse += right->slotuse;
3475
+ right->slotuse = 0;
3476
+
3477
+ return btree_fixmerge;
3478
+ }
3479
+
3480
+ //! Balance two leaf nodes. The function moves key/data pairs from right to
3481
+ //! left so that both nodes are equally filled. The parent node is updated
3482
+ //! if possible.
3483
+ static result_t shift_left_leaf(LeafNode* left, LeafNode* right,
3484
+ InnerNode* parent, unsigned int parentslot)
3485
+ {
3486
+ TLX_BTREE_ASSERT(left->is_leafnode() && right->is_leafnode());
3487
+ TLX_BTREE_ASSERT(parent->level == 1);
3488
+
3489
+ TLX_BTREE_ASSERT(left->next_leaf == right);
3490
+ TLX_BTREE_ASSERT(left == right->prev_leaf);
3491
+
3492
+ TLX_BTREE_ASSERT(left->slotuse < right->slotuse);
3493
+ TLX_BTREE_ASSERT(parent->childid[parentslot] == left);
3494
+
3495
+ unsigned int shiftnum = (right->slotuse - left->slotuse) >> 1;
3496
+
3497
+ TLX_BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to left "
3498
+ << left << " from right " << right
3499
+ << " with common parent " << parent
3500
+ << ".");
3501
+
3502
+ TLX_BTREE_ASSERT(left->slotuse + shiftnum < leaf_slotmax);
3503
+
3504
+ // copy the first items from the right node to the last slot in the left
3505
+ // node.
3506
+
3507
+ std::copy(right->slotdata, right->slotdata + shiftnum,
3508
+ left->slotdata + left->slotuse);
3509
+
3510
+ left->slotuse += shiftnum;
3511
+
3512
+ // shift all slots in the right node to the left
3513
+
3514
+ std::copy(right->slotdata + shiftnum, right->slotdata + right->slotuse,
3515
+ right->slotdata);
3516
+
3517
+ right->slotuse -= shiftnum;
3518
+
3519
+ // fixup parent
3520
+ if (parentslot < parent->slotuse)
3521
+ {
3522
+ parent->slotkey[parentslot] = left->key(left->slotuse - 1);
3523
+ return btree_ok;
3524
+ }
3525
+
3526
+ // the update is further up the tree
3527
+ return result_t(btree_update_lastkey, left->key(left->slotuse - 1));
3528
+ }
3529
+
3530
+ //! Balance two inner nodes. The function moves key/data pairs from right to
3531
+ //! left so that both nodes are equally filled. The parent node is updated
3532
+ //! if possible.
3533
+ static void shift_left_inner(InnerNode* left, InnerNode* right,
3534
+ InnerNode* parent, unsigned int parentslot)
3535
+ {
3536
+ TLX_BTREE_ASSERT(left->level == right->level);
3537
+ TLX_BTREE_ASSERT(parent->level == left->level + 1);
3538
+
3539
+ TLX_BTREE_ASSERT(left->slotuse < right->slotuse);
3540
+ TLX_BTREE_ASSERT(parent->childid[parentslot] == left);
3541
+
3542
+ unsigned int shiftnum = (right->slotuse - left->slotuse) >> 1;
3543
+
3544
+ TLX_BTREE_PRINT("Shifting (inner) " << shiftnum << " entries to left "
3545
+ << left << " from right " << right
3546
+ << " with common parent " << parent
3547
+ << ".");
3548
+
3549
+ TLX_BTREE_ASSERT(left->slotuse + shiftnum < inner_slotmax);
3550
+
3551
+ if (self_verify)
3552
+ {
3553
+ // find the left node's slot in the parent's children and compare to
3554
+ // parentslot
3555
+
3556
+ unsigned int leftslot = 0;
3557
+ while (leftslot <= parent->slotuse &&
3558
+ parent->childid[leftslot] != left)
3559
+ ++leftslot;
3560
+
3561
+ TLX_BTREE_ASSERT(leftslot < parent->slotuse);
3562
+ TLX_BTREE_ASSERT(parent->childid[leftslot] == left);
3563
+ TLX_BTREE_ASSERT(parent->childid[leftslot + 1] == right);
3564
+
3565
+ TLX_BTREE_ASSERT(leftslot == parentslot);
3566
+ }
3567
+
3568
+ // copy the parent's decision slotkey and childid to the first new key
3569
+ // on the left
3570
+ left->slotkey[left->slotuse] = parent->slotkey[parentslot];
3571
+ left->slotuse++;
3572
+
3573
+ // copy the other items from the right node to the last slots in the
3574
+ // left node.
3575
+ std::copy(right->slotkey, right->slotkey + shiftnum - 1,
3576
+ left->slotkey + left->slotuse);
3577
+ std::copy(right->childid, right->childid + shiftnum,
3578
+ left->childid + left->slotuse);
3579
+
3580
+ left->slotuse += shiftnum - 1;
3581
+
3582
+ // fixup parent
3583
+ parent->slotkey[parentslot] = right->slotkey[shiftnum - 1];
3584
+
3585
+ // shift all slots in the right node
3586
+ std::copy(right->slotkey + shiftnum, right->slotkey + right->slotuse,
3587
+ right->slotkey);
3588
+ std::copy(right->childid + shiftnum,
3589
+ right->childid + right->slotuse + 1, right->childid);
3590
+
3591
+ right->slotuse -= shiftnum;
3592
+ }
3593
+
3594
+ //! Balance two leaf nodes. The function moves key/data pairs from left to
3595
+ //! right so that both nodes are equally filled. The parent node is updated
3596
+ //! if possible.
3597
+ static void shift_right_leaf(LeafNode* left, LeafNode* right,
3598
+ InnerNode* parent, unsigned int parentslot)
3599
+ {
3600
+ TLX_BTREE_ASSERT(left->is_leafnode() && right->is_leafnode());
3601
+ TLX_BTREE_ASSERT(parent->level == 1);
3602
+
3603
+ TLX_BTREE_ASSERT(left->next_leaf == right);
3604
+ TLX_BTREE_ASSERT(left == right->prev_leaf);
3605
+ TLX_BTREE_ASSERT(parent->childid[parentslot] == left);
3606
+
3607
+ TLX_BTREE_ASSERT(left->slotuse > right->slotuse);
3608
+
3609
+ unsigned int shiftnum = (left->slotuse - right->slotuse) >> 1;
3610
+
3611
+ TLX_BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right "
3612
+ << right << " from left " << left
3613
+ << " with common parent " << parent
3614
+ << ".");
3615
+
3616
+ if (self_verify)
3617
+ {
3618
+ // find the left node's slot in the parent's children
3619
+ unsigned int leftslot = 0;
3620
+ while (leftslot <= parent->slotuse &&
3621
+ parent->childid[leftslot] != left)
3622
+ ++leftslot;
3623
+
3624
+ TLX_BTREE_ASSERT(leftslot < parent->slotuse);
3625
+ TLX_BTREE_ASSERT(parent->childid[leftslot] == left);
3626
+ TLX_BTREE_ASSERT(parent->childid[leftslot + 1] == right);
3627
+
3628
+ TLX_BTREE_ASSERT(leftslot == parentslot);
3629
+ }
3630
+
3631
+ // shift all slots in the right node
3632
+
3633
+ TLX_BTREE_ASSERT(right->slotuse + shiftnum < leaf_slotmax);
3634
+
3635
+ std::copy_backward(right->slotdata, right->slotdata + right->slotuse,
3636
+ right->slotdata + right->slotuse + shiftnum);
3637
+
3638
+ right->slotuse += shiftnum;
3639
+
3640
+ // copy the last items from the left node to the first slot in the right
3641
+ // node.
3642
+ std::copy(left->slotdata + left->slotuse - shiftnum,
3643
+ left->slotdata + left->slotuse, right->slotdata);
3644
+
3645
+ left->slotuse -= shiftnum;
3646
+
3647
+ parent->slotkey[parentslot] = left->key(left->slotuse - 1);
3648
+ }
3649
+
3650
+ //! Balance two inner nodes. The function moves key/data pairs from left to
3651
+ //! right so that both nodes are equally filled. The parent node is updated
3652
+ //! if possible.
3653
+ static void shift_right_inner(InnerNode* left, InnerNode* right,
3654
+ InnerNode* parent, unsigned int parentslot)
3655
+ {
3656
+ TLX_BTREE_ASSERT(left->level == right->level);
3657
+ TLX_BTREE_ASSERT(parent->level == left->level + 1);
3658
+
3659
+ TLX_BTREE_ASSERT(left->slotuse > right->slotuse);
3660
+ TLX_BTREE_ASSERT(parent->childid[parentslot] == left);
3661
+
3662
+ unsigned int shiftnum = (left->slotuse - right->slotuse) >> 1;
3663
+
3664
+ TLX_BTREE_PRINT("Shifting (leaf) " << shiftnum << " entries to right "
3665
+ << right << " from left " << left
3666
+ << " with common parent " << parent
3667
+ << ".");
3668
+
3669
+ if (self_verify)
3670
+ {
3671
+ // find the left node's slot in the parent's children
3672
+ unsigned int leftslot = 0;
3673
+ while (leftslot <= parent->slotuse &&
3674
+ parent->childid[leftslot] != left)
3675
+ ++leftslot;
3676
+
3677
+ TLX_BTREE_ASSERT(leftslot < parent->slotuse);
3678
+ TLX_BTREE_ASSERT(parent->childid[leftslot] == left);
3679
+ TLX_BTREE_ASSERT(parent->childid[leftslot + 1] == right);
3680
+
3681
+ TLX_BTREE_ASSERT(leftslot == parentslot);
3682
+ }
3683
+
3684
+ // shift all slots in the right node
3685
+
3686
+ TLX_BTREE_ASSERT(right->slotuse + shiftnum < inner_slotmax);
3687
+
3688
+ std::copy_backward(right->slotkey, right->slotkey + right->slotuse,
3689
+ right->slotkey + right->slotuse + shiftnum);
3690
+ std::copy_backward(right->childid, right->childid + right->slotuse + 1,
3691
+ right->childid + right->slotuse + 1 + shiftnum);
3692
+
3693
+ right->slotuse += shiftnum;
3694
+
3695
+ // copy the parent's decision slotkey and childid to the last new key on
3696
+ // the right
3697
+ right->slotkey[shiftnum - 1] = parent->slotkey[parentslot];
3698
+
3699
+ // copy the remaining last items from the left node to the first slot in
3700
+ // the right node.
3701
+ std::copy(left->slotkey + left->slotuse - shiftnum + 1,
3702
+ left->slotkey + left->slotuse, right->slotkey);
3703
+ std::copy(left->childid + left->slotuse - shiftnum + 1,
3704
+ left->childid + left->slotuse + 1, right->childid);
3705
+
3706
+ // copy the first to-be-removed key from the left node to the parent's
3707
+ // decision slot
3708
+ parent->slotkey[parentslot] = left->slotkey[left->slotuse - shiftnum];
3709
+
3710
+ left->slotuse -= shiftnum;
3711
+ }
3712
+
3713
+ //! \}
3714
+
3715
+ #ifdef TLX_BTREE_DEBUG
3716
+
3717
+ public:
3718
+ //! \name Debug Printing
3719
+ //! \{
3720
+
3721
+ //! Print out the B+ tree structure with keys onto the given ostream. This
3722
+ //! function requires that the header is compiled with TLX_BTREE_DEBUG and
3723
+ //! that key_type is printable via std::ostream.
3724
+ void print(std::ostream& os) const
3725
+ {
3726
+ if (root_)
3727
+ {
3728
+ print_node(os, root_, 0, true);
3729
+ }
3730
+ }
3731
+
3732
+ //! Print out only the leaves via the double linked list.
3733
+ void print_leaves(std::ostream& os) const
3734
+ {
3735
+ os << "leaves:" << std::endl;
3736
+
3737
+ const LeafNode* n = head_leaf_;
3738
+
3739
+ while (n)
3740
+ {
3741
+ os << " " << n << std::endl;
3742
+
3743
+ n = n->next_leaf;
3744
+ }
3745
+ }
3746
+
3747
+ private:
3748
+ //! Recursively descend down the tree and print out nodes.
3749
+ static void print_node(std::ostream& os, const node* node,
3750
+ unsigned int depth = 0, bool recursive = false)
3751
+ {
3752
+ for (unsigned int i = 0; i < depth; i++)
3753
+ os << " ";
3754
+
3755
+ os << "node " << node << " level " << node->level << " slotuse "
3756
+ << node->slotuse << std::endl;
3757
+
3758
+ if (node->is_leafnode())
3759
+ {
3760
+ const LeafNode* leafnode = static_cast<const LeafNode*>(node);
3761
+
3762
+ for (unsigned int i = 0; i < depth; i++)
3763
+ os << " ";
3764
+ os << " leaf prev " << leafnode->prev_leaf << " next "
3765
+ << leafnode->next_leaf << std::endl;
3766
+
3767
+ for (unsigned int i = 0; i < depth; i++)
3768
+ os << " ";
3769
+
3770
+ for (unsigned short slot = 0; slot < leafnode->slotuse; ++slot)
3771
+ {
3772
+ // os << leafnode->key(slot) << " "
3773
+ // << "(data: " << leafnode->slotdata[slot] << ") ";
3774
+ os << leafnode->key(slot) << " ";
3775
+ }
3776
+ os << std::endl;
3777
+ }
3778
+ else
3779
+ {
3780
+ const InnerNode* innernode = static_cast<const InnerNode*>(node);
3781
+
3782
+ for (unsigned int i = 0; i < depth; i++)
3783
+ os << " ";
3784
+
3785
+ for (unsigned short slot = 0; slot < innernode->slotuse; ++slot)
3786
+ {
3787
+ os << "(" << innernode->childid[slot] << ") "
3788
+ << innernode->slotkey[slot] << " ";
3789
+ }
3790
+ os << "(" << innernode->childid[innernode->slotuse] << ")"
3791
+ << std::endl;
3792
+
3793
+ if (recursive)
3794
+ {
3795
+ for (unsigned short slot = 0; slot < innernode->slotuse + 1;
3796
+ ++slot)
3797
+ {
3798
+ print_node(os, innernode->childid[slot], depth + 1,
3799
+ recursive);
3800
+ }
3801
+ }
3802
+ }
3803
+ }
3804
+
3805
+ //! \}
3806
+ #endif
3807
+
3808
+ public:
3809
+ //! \name Verification of B+ Tree Invariants
3810
+ //! \{
3811
+
3812
+ //! Run a thorough verification of all B+ tree invariants. The program
3813
+ //! aborts via tlx_die_unless() if something is wrong.
3814
+ void verify() const
3815
+ {
3816
+ key_type minkey, maxkey;
3817
+ tree_stats vstats;
3818
+
3819
+ if (root_)
3820
+ {
3821
+ verify_node(root_, &minkey, &maxkey, vstats);
3822
+
3823
+ tlx_die_unless(vstats.size == stats_.size);
3824
+ tlx_die_unless(vstats.leaves == stats_.leaves);
3825
+ tlx_die_unless(vstats.inner_nodes == stats_.inner_nodes);
3826
+
3827
+ verify_leaflinks();
3828
+ }
3829
+ }
3830
+
3831
+ private:
3832
+ //! Recursively descend down the tree and verify each node
3833
+ void verify_node(const node* n, key_type* minkey, key_type* maxkey,
3834
+ tree_stats& vstats) const
3835
+ {
3836
+ TLX_BTREE_PRINT("verifynode " << n);
3837
+
3838
+ if (n->is_leafnode())
3839
+ {
3840
+ const LeafNode* leaf = static_cast<const LeafNode*>(n);
3841
+
3842
+ tlx_die_unless(leaf == root_ || !leaf->is_underflow());
3843
+ tlx_die_unless(leaf->slotuse > 0);
3844
+
3845
+ for (unsigned short slot = 0; slot < leaf->slotuse - 1; ++slot)
3846
+ {
3847
+ tlx_die_unless(
3848
+ key_lessequal(leaf->key(slot), leaf->key(slot + 1)));
3849
+ }
3850
+
3851
+ *minkey = leaf->key(0);
3852
+ *maxkey = leaf->key(leaf->slotuse - 1);
3853
+
3854
+ vstats.leaves++;
3855
+ vstats.size += leaf->slotuse;
3856
+ }
3857
+ else // !n->is_leafnode()
3858
+ {
3859
+ const InnerNode* inner = static_cast<const InnerNode*>(n);
3860
+ vstats.inner_nodes++;
3861
+
3862
+ tlx_die_unless(inner == root_ || !inner->is_underflow());
3863
+ tlx_die_unless(inner->slotuse > 0);
3864
+
3865
+ for (unsigned short slot = 0; slot < inner->slotuse - 1; ++slot)
3866
+ {
3867
+ tlx_die_unless(
3868
+ key_lessequal(inner->key(slot), inner->key(slot + 1)));
3869
+ }
3870
+
3871
+ for (unsigned short slot = 0; slot <= inner->slotuse; ++slot)
3872
+ {
3873
+ const node* subnode = inner->childid[slot];
3874
+ key_type subminkey = key_type();
3875
+ key_type submaxkey = key_type();
3876
+
3877
+ tlx_die_unless(subnode->level + 1 == inner->level);
3878
+ verify_node(subnode, &subminkey, &submaxkey, vstats);
3879
+
3880
+ TLX_BTREE_PRINT("verify subnode " << subnode << ": "
3881
+ << subminkey << " - "
3882
+ << submaxkey);
3883
+
3884
+ if (slot == 0)
3885
+ *minkey = subminkey;
3886
+ else
3887
+ tlx_die_unless(
3888
+ key_greaterequal(subminkey, inner->key(slot - 1)));
3889
+
3890
+ if (slot == inner->slotuse)
3891
+ *maxkey = submaxkey;
3892
+ else
3893
+ tlx_die_unless(key_equal(inner->key(slot), submaxkey));
3894
+
3895
+ if (inner->level == 1 && slot < inner->slotuse)
3896
+ {
3897
+ // children are leaves and must be linked together in the
3898
+ // correct order
3899
+ const LeafNode* leafa =
3900
+ static_cast<const LeafNode*>(inner->childid[slot]);
3901
+ const LeafNode* leafb =
3902
+ static_cast<const LeafNode*>(inner->childid[slot + 1]);
3903
+
3904
+ tlx_die_unless(leafa->next_leaf == leafb);
3905
+ tlx_die_unless(leafa == leafb->prev_leaf);
3906
+ }
3907
+ if (inner->level == 2 && slot < inner->slotuse)
3908
+ {
3909
+ // verify leaf links between the adjacent inner nodes
3910
+ const InnerNode* parenta =
3911
+ static_cast<const InnerNode*>(inner->childid[slot]);
3912
+ const InnerNode* parentb =
3913
+ static_cast<const InnerNode*>(inner->childid[slot + 1]);
3914
+
3915
+ const LeafNode* leafa = static_cast<const LeafNode*>(
3916
+ parenta->childid[parenta->slotuse]);
3917
+ const LeafNode* leafb =
3918
+ static_cast<const LeafNode*>(parentb->childid[0]);
3919
+
3920
+ tlx_die_unless(leafa->next_leaf == leafb);
3921
+ tlx_die_unless(leafa == leafb->prev_leaf);
3922
+ }
3923
+ }
3924
+ }
3925
+ }
3926
+
3927
+ //! Verify the double linked list of leaves.
3928
+ void verify_leaflinks() const
3929
+ {
3930
+ const LeafNode* n = head_leaf_;
3931
+
3932
+ tlx_die_unless(n->level == 0);
3933
+ tlx_die_unless(!n || n->prev_leaf == nullptr);
3934
+
3935
+ unsigned int testcount = 0;
3936
+
3937
+ while (n)
3938
+ {
3939
+ tlx_die_unless(n->level == 0);
3940
+ tlx_die_unless(n->slotuse > 0);
3941
+
3942
+ for (unsigned short slot = 0; slot < n->slotuse - 1; ++slot)
3943
+ {
3944
+ tlx_die_unless(key_lessequal(n->key(slot), n->key(slot + 1)));
3945
+ }
3946
+
3947
+ testcount += n->slotuse;
3948
+
3949
+ if (n->next_leaf)
3950
+ {
3951
+ tlx_die_unless(key_lessequal(n->key(n->slotuse - 1),
3952
+ n->next_leaf->key(0)));
3953
+
3954
+ tlx_die_unless(n == n->next_leaf->prev_leaf);
3955
+ }
3956
+ else
3957
+ {
3958
+ tlx_die_unless(tail_leaf_ == n);
3959
+ }
3960
+
3961
+ n = n->next_leaf;
3962
+ }
3963
+
3964
+ tlx_die_unless(testcount == size());
3965
+ }
3966
+
3967
+ //! \}
3968
+ };
3969
+
3970
+ //! \}
3971
+ //! \}
3972
+
3973
+ } // namespace tlx
3974
+
3975
+ #endif // !TLX_CONTAINER_BTREE_HEADER
3976
+
3977
+ /******************************************************************************/