sorted-btree
Version:
A sorted list of key-value pairs in a fast, typed in-memory B+ tree with a powerful API.
2 lines (1 loc) • 8.03 kB
JavaScript
;Object.defineProperty(exports,"__esModule",{value:!0}),exports.buildFromDecomposition=exports.decompose=void 0;var b_tree_1=require("../b+tree"),shared_1=require("./shared"),parallelWalk_1=require("./parallelWalk"),decomposeLoadFactor=.7;function decompose(e,a,n,r){void 0===r&&(r=!1);var i=e._maxNodeSize,s=e._compare;(0,b_tree_1.check)(0<e._root.size()&&0<a._root.size(),"decompose requires non-empty inputs");function t(e){var a=e.keys.length<K?-1:0;_.push(a),k.push(e)}function u(e,a){(0,shared_1.makeLeavesFrom)(x,I,i,decomposeLoadFactor,t),x.length=0,I.length=0,e.isLeaf&&e.keys.length<K?(_.push(-1),k.push(e.clone())):(e.isShared=!0,_.push(a),k.push(e)),L<a&&(b=_.length-1,L=a)}function f(){void 0!==S&&(u(S.node,S.height),S=void 0)}function h(e,a){for(var n=e.spine,r=a;0<=r;--r){var i=n[r].payload;if(i.disqualified)break;i.disqualified=!0}}function l(){return{disqualified:!1}}function o(e,a,n){for(var r=e.keys,i=e.values,t=a;t<n;++t)x.push(r[t]),I.push(i[t])}function d(e,a,n,r,i){(0,b_tree_1.check)(!0===a.disqualified,"onMoveInLeaf: leaf must be disqualified"),(n=i?n+1:n)<r&&o(e,n,r)}function p(e,a,n,r,i){S=void 0,a.disqualified?(r=r?n+1:n)<(n=e.keys.length)&&o(e,r,n):(S={node:e,height:0},0===i.spine.length&&f())}function c(e,a,n,r,i,t,l){var s=e.children,o=a-1;if(t!=t||t===Number.POSITIVE_INFINITY)if(n.disqualified){f();for(var d=s.length,p=r+1;p<d;++p)u(s[p],o)}else if(t===Number.POSITIVE_INFINITY){if(e.keys.length<K)for(var p=r;p<s.length;++p)u(s[p],o);else u(e,a);S=void 0}else S={node:e,height:a};else{0<t&&h(l,i),f();for(p=r+1;p<t;++p)u(s[p],o)}}function v(e,a,n,r,i){if(0<r){h(i,n);for(var t=e.children,l=a-1,s=0;s<r;++s)u(t[s],l)}}function g(e,a,n,r){(0<a||(0,b_tree_1.areOverlapping)(e.minKey(),e.maxKey(),(0,parallelWalk_1.getKey)(r),r.leaf.maxKey(),s))&&(n.leafPayload.disqualified=!0,r.leafPayload.disqualified=!0,h(n,n.spine.length-1),h(r,r.spine.length-1),o(e,0,a))}var y,m,_=[],k=[],x=[],I=[],b=-1,L=-1,S=void 0,K=Math.floor(i/2),W=e._root.maxKey(),F=a._root.maxKey(),N=0<=s(W,F)?W:F,O=(0,parallelWalk_1.createCursor)(e,l,g,d,p,c,v),e=function(e,a){var n=(0,parallelWalk_1.getKey)(e),r=(0,parallelWalk_1.getKey)(a),i=a.leaf.maxKey();(0,b_tree_1.areOverlapping)(n,e.leaf.maxKey(),r,i,s)&&(e.leafPayload.disqualified=!0);for(var t=0;t<e.spine.length;++t){var l=e.spine[t];(0,b_tree_1.areOverlapping)(n,l.node.maxKey(),r,i,s)&&(l.payload.disqualified=!0)}};e(O,m=r?(y={disqualified:!0},(0,parallelWalk_1.createCursor)(a,function(){return y},function(e,a,n,r){(0<a||(0,b_tree_1.areOverlapping)(e.minKey(),e.maxKey(),(0,parallelWalk_1.getKey)(r),r.leaf.maxKey(),s))&&(r.leafPayload.disqualified=!0,h(r,r.spine.length-1))},parallelWalk_1.noop,parallelWalk_1.noop,function(e,a,n,r,i,t,l){0<t&&h(l,i)},function(e,a,n,r,i){0<r&&h(i,n)})):(0,parallelWalk_1.createCursor)(a,l,g,d,p,c,v)),e(m,O);for(var q=O,M=m,R=s((0,parallelWalk_1.getKey)(q),(0,parallelWalk_1.getKey)(M));;){var z=0===R;if(z){var w=(0,parallelWalk_1.getKey)(q),C=n(w,O.leaf.values[O.leafIndex],m.leaf.values[m.leafIndex]);void 0!==C&&(x.push(w),I.push(C));w=(0,parallelWalk_1.moveForwardOne)(M,q),C=(0,parallelWalk_1.moveForwardOne)(q,M);if(w||C){w&&C||(w?(0,parallelWalk_1.moveTo)(q,M,N,!1,!1):(0,parallelWalk_1.moveTo)(M,q,N,!1,!1));break}R=s((0,parallelWalk_1.getKey)(q),(0,parallelWalk_1.getKey)(M))}else{R<0&&(E=M,M=q,q=E);var w=(0,parallelWalk_1.moveTo)(M,q,(0,parallelWalk_1.getKey)(q),!0,z),E=w[0],w=w[1];if(E){(0,parallelWalk_1.moveTo)(q,M,N,!1,z);break}R=w?0:-1}}return(0,shared_1.makeLeavesFrom)(x,I,i,decomposeLoadFactor,t),L<0&&0<_.length&&(b=0),{heights:_,nodes:k,tallestIndex:b}}function buildFromDecomposition(e,a,n,r,i){var t=n.heights,l=n.nodes,s=n.tallestIndex;(0,b_tree_1.check)(t.length===l.length,"Decompose result has mismatched heights and nodes.");var o=t.length,d=[l[s]],n={branchingFactor:a,spine:d,sideIndex:getRightmostIndex,sideInsertionIndex:getRightInsertionIndex,splitOffSide:splitOffRightSide,balanceLeaves:balanceLeavesRight,updateMax:updateRightMax,mergeLeaves:mergeRightEntries};s+1<=o-1&&(updateFrontier(n,0),processSide(t,l,s+1,o,1,n));a={branchingFactor:a,spine:d,sideIndex:getLeftmostIndex,sideInsertionIndex:getLeftmostIndex,splitOffSide:splitOffLeftSide,balanceLeaves:balanceLeavesLeft,updateMax:parallelWalk_1.noop,mergeLeaves:mergeLeftEntries};0<=s-1&&(updateFrontier(a,0),processSide(t,l,s-1,-1,-1,a));i=new e(void 0,r,i);return i._root=d[0],i}function processSide(e,a,n,r,i,t){for(var l=t.spine,s=t.sideIndex,o=0,d=l[0];!d.isShared&&o<l.length-1;)o++,d=d.children[s(d)];for(var p=new Array(l.length).fill(0),u=n;u!=r;u+=i){var f=l.length-1,h=a[u],c=e[u],v=-1===c;(0,b_tree_1.check)(c<=f,"Subtree taller than spine during reconstruction.");var g=f-(c+1);ensureNotShared(t,o,g);var y=void 0,m=void 0;v?((0,b_tree_1.check)(!0!==h.isShared),y=m=h.keys.length):(y=1,m=h.size());f=findSplitCascadeEndDepth(t,g,y),c=Math.max(0,f);updateSizeAndMax(t,p,o,c);y=void 0,f=void 0,f=v?(y=splitUpwardsAndInsertEntries(t,g,h),g-1):(y=splitUpwardsAndInsert(t,g,h)[0],g);y&&(l[0]=y,p.push(0),f++),o=f+1,p[f]+=m,updateFrontier(t,c),(0,b_tree_1.check)(o===l.length-1||!0===l[o].isShared,"Non-leaf subtrees must be shared."),(0,b_tree_1.check)(p.length===l.length,"Unflushed sizes length mismatch after root split.")}updateSizeAndMax(t,p,o,0)}function splitUpwardsAndInsert(e,a,n){var r=e.spine,i=e.branchingFactor,t=e.sideIndex,l=e.sideInsertionIndex,s=e.splitOffSide,o=e.updateMax;if(0<=a){var d=void 0,e=r[a];e.keys.length===i&&(e=d=s(e));for(var p=a-1;d&&0<=p;){var u=r[p],f=t(u);o(u,u.children[f].maxKey()),d=u.keys.length<i?void insertNoCount(u,l(u),d):(insertNoCount(u=s(u),l(u),d),u),p--}var h=void 0;return void 0!==d&&(c=r[0],insertNoCount(h=new b_tree_1.BNodeInternal([c],c.size()+d.size()),l(h),d)),insertNoCount(e,l(e),n),[h,e]}var c=r[0];return insertNoCount(h=new b_tree_1.BNodeInternal([c],c.size()),l(h),n),[h,h]}function splitUpwardsAndInsertEntries(e,a,n){var r=e.branchingFactor,i=e.spine,t=e.balanceLeaves,l=e.mergeLeaves,s=n.keys.length,i=i[a];if(!(i.keys.length+s<=r)){e=splitUpwardsAndInsert(e,a-1,n),a=e[0];return t(e[1],n,Math.floor(r/2)-s),a}l(i,n)}function ensureNotShared(e,a,n){var r=e.spine,i=e.sideIndex;if(!(n<0)){0===a&&(e=r[0],r[0]=e.clone());for(var t=Math.max(a,1);t<=n;t++){var l=r[t-1],s=i(l),o=l.children[s].clone();l.children[s]=o,r[t]=o}}}function updateSizeAndMax(e,a,n,r){for(var i=e.spine,t=e.updateMax,l=i[n].maxKey(),s=n-1;r<=s;s--){var o=a[s];(a[s]=0)<s&&(a[s-1]+=o);var d=i[s];d._size+=o,t(d,l)}}function updateFrontier(e,a){var n=e.spine,r=e.sideIndex;(0,b_tree_1.check)(n.length>a,"updateFrontier: depthLastValid exceeds frontier height");e=n[a];if(!e.isLeaf){for(var i=e.children[r(e)],t=a+1;!i.isLeaf;){var l=i,i=(n[t]=l).children[r(l)];t++}n[t]=i}}function findSplitCascadeEndDepth(e,a,n){var r=e.spine,i=e.branchingFactor;if(0<=a){var t=a;if(r[t].keys.length+n<=i)return t;for(t--;0<=t;){if(r[t].keys.length<i)return t;t--}}return-1}function insertNoCount(e,a,n){e.children.splice(a,0,n),e.keys.splice(a,0,n.maxKey())}function getLeftmostIndex(){return 0}function getRightmostIndex(e){return e.children.length-1}function getRightInsertionIndex(e){return e.children.length}function splitOffRightSide(e){return e.splitOffRightSide()}function splitOffLeftSide(e){return e.splitOffLeftSide()}function balanceLeavesRight(e,a,n){var r=e.children.length-2,i=e.children[r],t=i.keys.length-n,n=i.keys.splice(t),t=i.values.splice(t);a.keys.unshift.apply(a.keys,n),a.values.unshift.apply(a.values,t),e.keys[r]=i.maxKey()}function balanceLeavesLeft(e,a,n){var r=e.children[1],i=r.keys.splice(0,n),n=r.values.splice(0,n);a.keys.push.apply(a.keys,i),a.values.push.apply(a.values,n),e.keys[0]=a.maxKey()}function updateRightMax(e,a){e.keys[e.keys.length-1]=a}function mergeRightEntries(e,a){e.keys.push.apply(e.keys,a.keys),e.values.push.apply(e.values,a.values)}function mergeLeftEntries(e,a){e.keys.unshift.apply(e.keys,a.keys),e.values.unshift.apply(e.values,a.values)}exports.decompose=decompose,exports.buildFromDecomposition=buildFromDecomposition;