public int GetHashCode(IComputedLengthNode <T> node) { NodeType nt = node.Type; if (nt == NodeType.Leaf) { var comparer = EqualityComparer <T> .Default; return(comparer.GetHashCode(node.Get(1, 1, 1, 0, 0, 0))); } else { unchecked { int d = 31 * RuntimeHelpers.GetHashCode(node.Left) + 53 * RuntimeHelpers.GetHashCode(node.Right); if (nt == NodeType.X) { return(67 * d); } else if (nt == NodeType.Y) { return(89 * d); } else { return(113 * d); } } } }
public override IComputedLengthNode <T> Get(Dimension dim, IComputedLengthNode <T> left, IComputedLengthNode <T> right) { if ((left.Type == NodeType.Leaf) && (right.Type == NodeType.Leaf)) { // Both children are leaf nodes var comparer = EqualityComparer <T> .Default; var leftItem = left.Get(1, 1, 1, 0, 0, 0); var rightItem = right.Get(1, 1, 1, 0, 0, 0); // Check if both leaf-children store the same value if (comparer.Equals(leftItem, rightItem)) { // They store the same value, this node and its children should be merged into one leaf node. // Since the leaf nodes only store the value, we can just return either one of the children and have the same effect. return(left); } } IComputedLengthNode <T> test = Create(dim, left, right); IComputedLengthNode <T> node; if (nodes.TryGetValue(test, out node)) { return(node); } else { Cache(test); return(test); } }
public override IComputedLengthNode <T> Get(Dimension dim, IComputedLengthNode <T> left, IComputedLengthNode <T> right) { if ((left.Type == NodeType.Leaf) && (right.Type == NodeType.Leaf)) { // Both children are leaf nodes var comparer = EqualityComparer <T> .Default; var leftItem = left.Get(1, 1, 1, 0, 0, 0); var rightItem = right.Get(1, 1, 1, 0, 0, 0); // Check if both leaf-children store the same value if (comparer.Equals(leftItem, rightItem)) { // They store the same value, this node and its children should be merged into one leaf node. // Since the leaf nodes only store the value, we can just return either one of the children and have the same effect. return(left); } } if (dim == Dimension.X) { return(new XNode <T>(left, right)); } else if (dim == Dimension.Y) { return(new YNode <T>(left, right)); } else { return(new ZNode <T>(left, right)); } }
public T this[uint x, uint y, uint z] { get { assertBounds(x, y, z); return(node.Get(xLength, yLength, zLength, x, y, z)); } }
public bool IsCached(IComputedLengthNode <T> node) { if (node.Type == NodeType.Leaf) { return(leaves.ContainsKey(node.Get(1, 1, 1, 0, 0, 0))); } else { return(heights.ContainsKey(node)); } }
public T Get(uint xlen, uint ylen, uint zlen, uint x, uint y, uint z) { uint leftLen = LeftLength(xlen, ylen, zlen); // Choose which child to traverse down if (y < leftLen) { return(left.Get(xlen, leftLen, zlen, x, y, z)); } else { uint rightLen = RightLength(xlen, ylen, zlen); return(right.Get(xlen, rightLen, zlen, x, y - leftLen, z)); } }
public bool Equals(IComputedLengthNode <T> x, IComputedLengthNode <T> y) { if (x.Type == y.Type) { if (x.Type == NodeType.Leaf) { var comparer = EqualityComparer <T> .Default; var xItem = x.Get(1, 1, 1, 0, 0, 0); var yItem = y.Get(1, 1, 1, 0, 0, 0); return(comparer.Equals(xItem, yItem)); } else { return(object.ReferenceEquals(x.Left, y.Left) && object.ReferenceEquals(x.Right, y.Right)); } } else { return(false); } }
private void Cache(IComputedLengthNode <T> node) { if (node.Type == NodeType.Leaf) { T item = node.Get(1, 1, 1, 0, 0, 0); leaves[item] = node; } else { bool bothCached = IsCached(node.Left) && IsCached(node.Right); if (bothCached) { int newHeight = Math.Max(GetHeight(node.Left), GetHeight(node.Right)) + 1; if (newHeight <= maxHeight) { nodes[node] = node; heights[node] = newHeight; } } } }
// Return a new tree with {item} set at the specified position public virtual IComputedLengthNode <T> WithSet(IComputedLengthNode <T> node, uint xlen, uint ylen, uint zlen, uint x, uint y, uint z, T item) { NodeType type = node.Type; if (type == NodeType.Leaf) { var comparer = EqualityComparer <T> .Default; var nodeItem = node.Get(1, 1, 1, 0, 0, 0); if (comparer.Equals(nodeItem, item)) { // Trying to set the item to the same thing return(node); } else if (xlen == 1 && ylen == 1 && zlen == 1) { // We have exactly one position, set the new value return(this.Get(item)); } else { // We need to set a new value somewhere in this node. Split this leaf node and keep trying to find a spot var splitNode = this.Split(node, xlen, ylen, zlen); return(this.WithSet(splitNode, xlen, ylen, zlen, x, y, z, item)); } } else { var left = node.Left; var right = node.Right; var nl = left; var nr = right; uint leftLen = node.LeftLength(xlen, ylen, zlen); uint rightLen = node.RightLength(xlen, ylen, zlen); Dimension dimension; if (type == NodeType.X) { dimension = Dimension.X; if (x < leftLen) { nl = this.WithSet(left, leftLen, ylen, zlen, x, y, z, item); } else { nr = this.WithSet(right, rightLen, ylen, zlen, x - leftLen, y, z, item); } } else if (type == NodeType.Y) { dimension = Dimension.Y; if (y < leftLen) { nl = this.WithSet(left, xlen, leftLen, zlen, x, y, z, item); } else { nr = this.WithSet(right, xlen, rightLen, zlen, x, y - leftLen, z, item); } } else { dimension = Dimension.Z; if (z < leftLen) { nl = this.WithSet(left, xlen, ylen, leftLen, x, y, z, item); } else { nr = this.WithSet(right, xlen, ylen, rightLen, x, y, z - leftLen, item); } } if (object.ReferenceEquals(nl, left) && object.ReferenceEquals(nr, right)) { // There was no change return(node); } // One of the children changed, transfer the changes up the tree return(this.Get(dimension, nl, nr)); } }