/// <summary> /// Returns a new stack with the top element popped. /// </summary> /// <returns>The new stack.</returns> public override IPersistentStack pop() { if ( _cnt == 0 ) throw new InvalidOperationException("Can't pop empty vector"); if ( _cnt == 1) return (IPersistentStack)EMPTY.withMeta(meta()); if ( _tail.Length > 1 ) { object[] newTail = new object[_tail.Length-1]; Array.Copy(_tail,newTail,newTail.Length); return new PersistentVector(meta(),_cnt-1,_shift,_root,newTail); } Box ptail = new Box(null); object[] newroot = popTail(_shift-5,_root,ptail); int newshift = _shift; if ( newroot == null ) newroot = RT.EMPTY_OBJECT_ARRAY; if ( _shift > 5 && newroot.Length == 1 ) { newroot = (Object[])newroot[0]; newshift -= 5; } return new PersistentVector(meta(),_cnt-1,newshift,newroot,(object[])ptail.Val); }
public INode assoc(int shift, int hash, object key, object val, Box addedLeaf) { if (_hash == hash) { int idx = findIndex(hash, key); if (idx != -1) { if (_leaves[idx].val() == val) return this; LeafNode[] newLeaves1 = (LeafNode[])_leaves.Clone(); // Note: do not set addedLeaf, since we are replacing newLeaves1[idx] = new LeafNode(hash, key, val); return new HashCollisionNode(hash, newLeaves1); } LeafNode[] newLeaves = new LeafNode[_leaves.Length + 1]; Array.Copy(_leaves, 0, newLeaves, 0, _leaves.Length); addedLeaf.Val = newLeaves[_leaves.Length] = new LeafNode(hash, key, val); return new HashCollisionNode(hash, newLeaves); } return BitmapIndexedNode.create(shift, this, hash, key, val, addedLeaf); }
public INode without(AtomicReference<Thread> edit, int shift, int hash, object key, Box removedLeaf) { int idx = Util.Mask(hash, shift); INode node = _array[idx]; if (node == null) return this; INode n = node.without(edit, shift + 5, hash, key, removedLeaf); if (n == node) return this; if (n == null) { if (_count <= 8) // shrink return pack(edit, idx); ArrayNode editable = EditAndSet(edit, idx, n); editable._count--; return editable; } return EditAndSet(edit, idx, n); }
public INode assoc(AtomicReference<Thread> edit, int shift, int hash, object key, object val, Box addedLeaf) { int bit = Bitpos(hash, shift); int idx = Index(bit); if ((_bitmap & bit) != 0) { object keyOrNull = _array[2 * idx]; object valOrNode = _array[2 * idx + 1]; if (keyOrNull == null) { INode n = ((INode)valOrNode).assoc(edit, shift + 5, hash, key, val, addedLeaf); if (n == valOrNode) return this; return EditAndSet(edit, 2 * idx + 1, n); } if (Util.equiv(key, keyOrNull)) { if (val == valOrNode) return this; return EditAndSet(edit, 2 * idx + 1, val); } addedLeaf.Val = addedLeaf; return EditAndSet(edit, 2*idx,null, 2*idx+1,CreateNode(edit,shift+5,keyOrNull,valOrNode,hash,key,val)); } else {int n = Util.BitCount(_bitmap); if ( n*2 < _array.Length ) { addedLeaf.Val = addedLeaf; BitmapIndexedNode editable = EnsureEditable(edit); Array.Copy(editable._array,2*idx,editable._array,2*(idx+1),2*(n-idx)); editable._array[2*idx] = key; editable._array[2*idx+1] = val; editable._bitmap |= bit; return editable; } if ( n >= 16 ) { INode[] nodes = new INode[32]; int jdx = Util.Mask(hash,shift); nodes[jdx] = EMPTY.assoc(edit,shift+5,hash,key,val,addedLeaf); int j=0; for ( int i=0; i<32; i++ ) if (((_bitmap>>i) & 1) != 0 ) { if ( _array[j] == null ) nodes[i] = (INode)_array[j+1]; else nodes[i] = EMPTY.assoc(edit,shift+5,Util.hash(_array[j]), _array[j], _array[j+1], addedLeaf); j += 2; } return new ArrayNode(edit,n+1,nodes); } else { object[] newArray = new object[2*(n+4)]; Array.Copy(_array,0,newArray,0,2*idx); newArray[2*idx] = key; addedLeaf.Val = addedLeaf; newArray[2 * idx + 1] = val; Array.Copy(_array,2*idx,newArray,2*(idx+1),2*(n-idx)); BitmapIndexedNode editable = EnsureEditable(edit); editable._array = newArray; editable._bitmap |= bit; return editable; } } }
/// <summary> /// Add a new key/value pair. /// </summary> /// <param name="key">The key</param> /// <param name="val">The value</param> /// <returns>A new map with key+value added.</returns> /// <remarks>Overwrites an exising value for the <paramref name="key"/>, if present.</remarks> public override IPersistentMap assoc(object key, object val) { if (key == null) { if (_hasNull && val == _nullValue) return this; return new PersistentHashMap(meta(), _hasNull ? _count : _count + 1, _root, true, val); } Box addedLeaf = new Box(null); INode newroot = (_root == null ? BitmapIndexedNode.EMPTY : _root) .assoc(0, Util.Hash(key), key, val, addedLeaf); return newroot == _root ? this : new PersistentHashMap(meta(), addedLeaf.Val == null ? _count : _count + 1, newroot, _hasNull, _nullValue); }
public INode assoc(int shift, int hash, object key, object val, Box addedLeaf) { int idx = Util.Mask(hash, shift); INode node = _array[idx]; if (node == null) return new ArrayNode(null, _count + 1, CloneAndSet(_array, idx, BitmapIndexedNode.EMPTY.assoc(shift + 5, hash, key, val, addedLeaf))); INode n = node.assoc(shift + 5, hash, key, val, addedLeaf); if (n == node) return this; return new ArrayNode(null, _count, CloneAndSet(_array, idx, n)); }
/// <summary> /// Add a node for a key /// </summary> /// <param name="t"></param> /// <param name="key"></param> /// <param name="val"></param> /// <param name="found"></param> /// <returns></returns> Node Add(Node t, object key, object val, Box found) { if (t == null) return val == null ? new Red(key) : new RedVal(key, val); int c = DoCompare(key, t.Key); if (c == 0) { found.Val = t; return null; } Node ins = c < 0 ? Add(t.Left, key, val, found) : Add(t.Right, key, val, found); if (ins == null) return null; return c < 0 ? t.AddLeft(ins) : t.AddRight(ins); }
public INode assoc(AtomicReference<Thread> edit, int shift, int hash, Object key, Object val, Box addedLeaf) { if (hash == _hash) { int idx = FindIndex(key); if (idx != -1) { if (_array[idx + 1] == val) return this; return EditAndSet(edit, idx + 1, val); } if (_array.Length > 2 * _count) { addedLeaf.Val = addedLeaf; HashCollisionNode editable = EditAndSet(edit, 2 * _count, key, 2 * _count + 1, val); editable._count++; return editable; } object[] newArray = new object[_array.Length + 2]; Array.Copy(_array, 0, newArray, 0, _array.Length); newArray[_array.Length] = key; newArray[_array.Length + 1] = val; addedLeaf.Val = addedLeaf; return EnsureEditable(edit, _count + 1, newArray); } // nest it in a bitmap node return new BitmapIndexedNode(edit, Bitpos(_hash, shift), new object[] { null, this, null, null }) .assoc(edit, shift, hash, key, val, addedLeaf); }
/// <summary> /// Add a new key/value pair. /// </summary> /// <param name="key">The key</param> /// <param name="val">The value</param> /// <returns>A new map with key+value added.</returns> /// <remarks>Throws an exception if <paramref name="key"/> has a value already.</remarks> public override IPersistentMap assocEx(object key, object val) { Box found = new Box(null); Node t = Add(_tree, key, val, found); if (t == null) throw new Exception("Key already present"); return new PersistentTreeMap(_comp, t.Blacken(), _count + 1, meta()); }
/// <summary> /// Remove a key entry. /// </summary> /// <param name="key">The key to remove</param> /// <returns>A new map with the key removed (or the same map if the key is not contained).</returns> public override IPersistentMap without(object key) { Box found = new Box(null); Node t = Remove(_tree, key, found); if (t == null) { if (found.Val == null) return this; return new PersistentTreeMap(meta(), _comp); } return new PersistentTreeMap(_comp, t.Blacken(), _count - 1, meta()); }
/// <summary> /// Add a new key/value pair. /// </summary> /// <param name="key">The key</param> /// <param name="val">The value</param> /// <returns>A new map with key+value added.</returns> /// <remarks>Overwrites an exising value for the <paramref name="key"/>, if present.</remarks> public override IPersistentMap assoc(object key, object val) { Box found = new Box(null); Node t = Add(_tree, key, val, found); if (t == null) { Node foundNode = (Node)found.Val; if (foundNode.Val == val) return this; return new PersistentTreeMap(_comp, Replace(_tree, key, val), _count, meta()); } return new PersistentTreeMap(_comp, t.Blacken(), _count + 1, meta()); }
private object[] pushTail(int level, object[] arr, object[] tailNode, Box expansion) { object newchild; if (level == 0) newchild = tailNode; else { newchild = pushTail(level - 5, (object[])arr[arr.Length - 1], tailNode, expansion); if (expansion.Val == null) { object[] ret1 = (object[])arr.Clone(); ret1[arr.Length - 1] = newchild; return ret1; } else newchild = expansion.Val; } //expansion if ( arr.Length == 32 ) { expansion.Val = new object[]{newchild}; return arr; } object[] ret = new object[arr.Length + 1]; Array.Copy(arr, ret, arr.Length); ret[arr.Length] = newchild; expansion.Val = null; return ret; }
private object[] popTail(int shift, object[] arr, Box ptail) { if ( shift > 0 ) { object[] newchild = popTail(shift-5,(object[])arr[arr.Length-1],ptail); if ( newchild != null ) { object[] ret1 = (object[])arr.Clone(); ret1[arr.Length-1] = newchild; return ret1; } } if ( shift == 0 ) ptail.Val = arr[arr.Length-1]; //contaction if( arr.Length == 1 ) return null; object[] ret = new Object[arr.Length-1]; Array.Copy(arr,ret,ret.Length); return ret; }
public INode assoc(int shift, int hash, object key, object val, Box addedLeaf) { if (hash == _hash) { if (Util.equals(key, _key)) { if (val == _val) return this; // note - do not set AddedLeaf, since we are replacing else return new LeafNode(hash, key, val); } else { // hash collision, same hash, different keys LeafNode newLeaf = new LeafNode(hash, key, val); addedLeaf.Val = newLeaf; return new HashCollisionNode(hash, this, newLeaf); } } else return BitmapIndexedNode.create(shift, this, hash, key, val, addedLeaf); }
Node Remove(Node t, object key, Box found) { if (t == null) return null; int c = DoCompare(key, t.Key); if (c == 0) { found.Val = t; return Append(t.Left, t.Right); } Node del = c < 0 ? Remove(t.Left, key, found) : Remove(t.Right, key, found); if (del == null && found.Val == null) return null; if (c < 0) return (t.Left is Black) ? BalanceLeftDel(t.Key, t.Val, del, t.Right) : MakeRed(t.Key, t.Val, del, t.Right); return (t.Right is Black) ? BalanceRightDel(t.Key, t.Val, t.Left, del) : MakeRed(t.Key, t.Val, t.Left, del); }
public INode assoc(int shift, int hash, object key, object val, Box addedLeaf) { if (_hash == hash) { int idx = FindIndex(key); if (idx != -1) { if (_array[idx + 1] == val) return this; return new HashCollisionNode(null, hash, _count, CloneAndSet(_array, idx + 1, val)); } object[] newArray = new object[_array.Length + 2]; Array.Copy(_array, 0, newArray, 0, _array.Length); newArray[_array.Length] = key; newArray[_array.Length + 1] = val; addedLeaf.Val = addedLeaf; return new HashCollisionNode(_edit, hash, _count + 1, newArray); } // nest it in a bitmap node return new BitmapIndexedNode(null, Bitpos(_hash, shift), new object[] { null, this }) .assoc(shift, hash, key, val, addedLeaf); }
/// <summary> /// Add a new key/value pair. /// </summary> /// <param name="key">The key</param> /// <param name="val">The value</param> /// <returns>A new map with key+value added.</returns> /// <remarks>Overwrites an exising value for the <paramref name="key"/>, if present.</remarks> public override IPersistentMap assoc(object key, object val) { Box addedLeaf = new Box(null); INode newroot = _root.assoc(0, Util.Hash(key), key, val, addedLeaf); return newroot == _root ? this : new PersistentHashMap(meta(), addedLeaf.Val == null ? _count : _count + 1, newroot); }
public INode without(AtomicReference<Thread> edit, int shift, int hash, Object key, Box removedLeaf) { int idx = FindIndex(key); if (idx == -1) return this; if (_count == 1) return null; HashCollisionNode editable = EnsureEditable(edit); editable._array[idx] = editable._array[2 * _count - 2]; editable._array[idx + 1] = editable._array[2 * _count - 1]; editable._array[2 * _count - 2] = editable._array[2 * _count - 1] = null; editable._count--; return editable; }
public INode assoc(int shift, int hash, object key, object val, Box addedLeaf) { int bit = bitpos(hash, shift); int idx = index(bit); if ((_bitmap & bit) != 0) { INode n = _nodes[idx].assoc(shift + 5, hash, key, val, addedLeaf); if (n == _nodes[idx]) return this; else { INode[] newnodes = (INode[])_nodes.Clone(); newnodes[idx] = n; return new BitmapIndexedNode(_bitmap, newnodes, shift); } } else { INode[] newnodes = new INode[_nodes.Length + 1]; Array.Copy(_nodes, 0, newnodes, 0, idx); addedLeaf.Val = newnodes[idx] = new LeafNode(hash, key, val); Array.Copy(_nodes, idx, newnodes, idx + 1, _nodes.Length - idx); return create(_bitmap | bit, newnodes, shift); } }
private static INode CreateNode(AtomicReference<Thread> edit, int shift, Object key1, Object val1, int key2hash, Object key2, Object val2) { int key1hash = Util.hash(key1); if (key1hash == key2hash) return new HashCollisionNode(null, key1hash, 2, new Object[] { key1, val1, key2, val2 }); Box _ = new Box(null); return BitmapIndexedNode.EMPTY .assoc(edit, shift, key1hash, key1, val1, _) .assoc(edit, shift, key2hash, key2, val2, _); }
internal static INode create(int shift, INode branch, int hash, object key, object val, Box addedLeaf) { return (new BitmapIndexedNode(bitpos(branch.getHash(), shift), new INode[] { branch }, shift)) .assoc(shift, hash, key, val, addedLeaf); }
public INode assoc(AtomicReference<Thread> edit, int shift, int hash, object key, object val, Box addedLeaf) { int idx = Util.Mask(hash, shift); INode node = _array[idx]; if (node == null) { ArrayNode editable = EditAndSet(edit, idx, BitmapIndexedNode.EMPTY.assoc(edit, shift + 5, hash, key, val, addedLeaf)); editable._count++; return editable; } INode n = node.assoc(edit, shift + 5, hash, key, val, addedLeaf); if (n == node) return this; return EditAndSet(edit, idx, n); }
public INode assoc(int shift, int hash, object key, object val, Box addedLeaf) { INode ret = new LeafNode(hash, key, val); addedLeaf.Val = ret; return ret; }
public INode assoc(int shift, int hash, object key, object val, Box addedLeaf) { int bit = Bitpos(hash, shift); int idx = Index(bit); if ((_bitmap & bit) != 0) { object keyOrNull = _array[2 * idx]; object valOrNode = _array[2 * idx + 1]; if (keyOrNull == null) { INode n = ((INode)valOrNode).assoc(shift + 5, hash, key, val, addedLeaf); if (n == valOrNode) return this; return new BitmapIndexedNode(null, _bitmap, CloneAndSet(_array, 2 * idx + 1, n)); } if ( Util.equiv(key,keyOrNull)) { if ( val == valOrNode) return this; return new BitmapIndexedNode(null,_bitmap,CloneAndSet(_array,2*idx+1,val)); } addedLeaf.Val = addedLeaf; return new BitmapIndexedNode(null,_bitmap, CloneAndSet(_array, 2*idx, null, 2*idx+1, CreateNode(shift+5,keyOrNull,valOrNode,hash,key,val))); } else { int n = Util.BitCount(_bitmap); if ( n >= 16 ) { INode [] nodes = new INode[32]; int jdx = Util.Mask(hash,shift); nodes[jdx] = EMPTY.assoc(shift+5,hash,key,val,addedLeaf); int j=0; for ( int i=0; i < 32; i++ ) if ( ( (_bitmap >>i) & 1) != 0 ) { if ( _array[j] == null ) nodes[i] = (INode) _array[j+1]; else nodes[i] = EMPTY.assoc(shift+5,Util.hash(_array[j]),_array[j],_array[j+1], addedLeaf); j += 2; } return new ArrayNode(null,n+1,nodes); } else { object[] newArray = new object[2*(n+1)]; Array.Copy(_array, 0, newArray, 0, 2*idx); newArray[2*idx] = key; addedLeaf.Val = addedLeaf; newArray[2*idx+1] = val; Array.Copy(_array, 2*idx, newArray, 2*(idx + 1), 2*(n - idx)); return new BitmapIndexedNode(null, _bitmap | bit, newArray); } } }
public INode assoc(int shift, int hash, object key, object val, Box addedLeaf) { int idx = Util.Mask(hash, shift); INode n = _nodes[idx].assoc(shift + 5, hash, key, val, addedLeaf); if (n == _nodes[idx]) return this; else { INode[] newNodes = (INode[])_nodes.Clone(); newNodes[idx] = n; return new FullNode(newNodes, shift); } }
public INode without(AtomicReference<Thread> edit, int shift, int hash, object key, Box removedLeaf) { int bit = Bitpos(hash, shift); if ((_bitmap & bit) == 0) return this; int idx = Index(bit); Object keyOrNull = _array[2 * idx]; Object valOrNode = _array[2 * idx + 1]; if (keyOrNull == null) { INode n = ((INode)valOrNode).without(edit, shift + 5, hash, key, removedLeaf); if (n == valOrNode) return this; if (n != null) return EditAndSet(edit, 2 * idx + 1, n); if (_bitmap == bit) return null; removedLeaf.Val = removedLeaf; return EditAndRemovePair(edit, bit, idx); } if (Util.equiv(key, keyOrNull)) { removedLeaf.Val = removedLeaf; // TODO: collapse return EditAndRemovePair(edit, bit, idx); } return this; }
/// <summary> /// Creates a new vector with a new item at the end. /// </summary> /// <param name="o">The item to add to the vector.</param> /// <returns>A new (immutable) vector with the objected added at the end.</returns> /// <remarks>Overrides <c>cons</c> in <see cref="IPersistentCollection">IPersistentCollection</see> to specialize the return value.</remarks> public override IPersistentVector cons(object val) { if (_tail.Length < 32) { object[] newTail = new object[_tail.Length + 1]; Array.Copy(_tail, newTail, _tail.Length); newTail[_tail.Length] = val; return new PersistentVector(meta(), _cnt + 1, _shift, _root, newTail); } Box expansion = new Box(null); object[] newroot = pushTail(_shift - 5, _root, _tail, expansion); int newshift = _shift; if (expansion.Val != null) { newroot = new object[] { newroot, expansion.Val }; newshift += 5; } return new PersistentVector(meta(), _cnt + 1, newshift, newroot, new object[] { val }); }