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));
            }
        }
예제 #4
0
 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));
     }
 }
예제 #6
0
        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;
                    }
                }
            }
        }
예제 #9
0
        // 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));
            }
        }