public RangedArray(int numberOfItems, TheFanciestMemory mem) { if (mem == null) throw new ArgumentNullException("mem"); _mem = mem; if (numberOfItems == 0) { _refNode = null; return; } _memInterval = mem.Malloc(numberOfItems); var root = NestingDepthTreeNode.Include(null, _memInterval.Offset, +1, +1).NewRoot; _refNode = NestingDepthTreeNode.Include(root, _memInterval.Offset + _memInterval.Length, -1, +1).AdjustedNode; }
public void Free(Interval span) { if (span.Offset < 0) throw new InvalidOperationException("Tried to free already-free memory."); if (span.Offset + span.Length > _memory.Count) throw new InvalidOperationException("Tried to free already-free memory."); for (var i = 0; i < span.Length; i++) { if (_memory[span.Offset + i].State == WordState.Free) throw new InvalidOperationException("Tried to free already-free memory."); } for (var i = 0; i < span.Length; i++) { _memory[span.Offset + i].State = WordState.Free; MemoryInUse -= 1; } }
public RangedArray(RangedArray other, Interval interval, TheFanciestMemory mem) { if (mem == null) throw new ArgumentNullException("mem"); _mem = mem; if (other._disposed) throw new ObjectDisposedException("other"); if (interval.Offset < 0) throw new ArgumentOutOfRangeException(); if (interval.Length < 0) throw new ArgumentOutOfRangeException(); if (interval.Offset + interval.Length > other._memInterval.Length) throw new ArgumentOutOfRangeException(); if (interval.Length == 0) { _refNode = null; return; } _memInterval = new Interval(other._memInterval.Offset + interval.Offset, interval.Length); var root = NestingDepthTreeNode.RootOf(other._refNode); root = NestingDepthTreeNode.Include(root, _memInterval.Offset, +1, +1).NewRoot; _refNode = NestingDepthTreeNode.Include(root, _memInterval.Offset + _memInterval.Length, -1, +1).AdjustedNode; }
public static Animation CreateAnimation() { var rng = new Random(12); var bigArraySize = 62; var ops = new List<Operation>(); ops.Add(new Operation {Key = -1, Interval = new Interval(1, bigArraySize)}); var remainingNumbers = Enumerable.Range(1, bigArraySize).ToList(); var activeIntervals = new Dictionary<int, Interval>(); activeIntervals[-1] = new Interval(1, bigArraySize); for (var i = 0; i < 50; i++) { if (activeIntervals.Count == 0) break; var rr = activeIntervals.ToArray(); if (i < 4) { //} || rng.Next(5) == 0) { var parent = activeIntervals[-1]; //rng.Next(activeIntervals.Count)].Value; var rep = 0; while (true) { var v1 = rng.Next(parent.Length); var v2 = rng.Next(parent.Length); if (v1 == v2) continue; rep += 1; if (rep < 10 && (!remainingNumbers.Contains(v1) || !remainingNumbers.Contains(v2))) continue; var offset = Math.Min(v2, v1); var len = Math.Max(v2, v1) - offset + 1; var x = new Interval(parent.Offset + offset, len/2); ops.Add(new Operation {Key = i, Interval = x}); activeIntervals[i] = x; break; } } else { var x = rng.Next(activeIntervals.Count); var k = i == 4 ? -1 : rr[x].Key; ops.Add(new Operation() {Key=k}); activeIntervals.Remove(k); } } return CreateAnimationOfOperations(new Interval(1 - 5, bigArraySize + 10), new Interval(1, bigArraySize), ops.ToArray()); }
///<summary>Returns all of the areas in the given interval where the tree would return zero if you queried the nesting depth there.</summary> public static IReadOnlyList<Interval> FindHolesIn(Interval interval, NestingDepthTreeNode root) { var relevantSegments = FindCoveredIntervals(root) .SkipWhile(e => !e.Overlaps(interval)) .TakeWhile(e => e.Overlaps(interval)) .ToArray(); var holeStarts = new[] {interval.Offset} .Concat(relevantSegments .Select(e => e.Offset + e.Length)); var holeEnds = relevantSegments .Select(e => e.Offset) .Concat(new[] {interval.Offset + interval.Length}); return holeStarts .Zip(holeEnds, (start, end) => new Interval(start, end - start)) .Where(e => e.Length > 0) .ToArray(); }
public RangedArray Slice(Interval interval) { return new RangedArray(this, interval, _mem); }
public RangedArray SliceArray(RangedArray array, Interval interval) { return new RangedArray(array, interval, this); }
public bool Overlaps(Interval other) { return this.Offset < other.Offset + other.Length && other.Offset < this.Offset + this.Length; }
private static Animation CreateAnimationOfOperations(Interval renderInterval, Interval targetInterval, params Operation[] operations) { var keyNodes = new Dictionary<int, Tuple<NestingDepthTreeNode, Interval, NestingDepthTreeNode>>(); var activeOperation = default(Operation); var dt = 1.0; var ani = new Animation(); ani.Add(new TextDesc("Using a Tree to Track Referenced Intervals", new Point(250, 5), new Point(0, 0), fontSize:20)); ani.Add(new TextDesc("Referenced" + Environment.NewLine + "Intervals", new Point(10, 80))); ani.Add(new TextDesc("Tree", new Point(10, 220))); ani.Add(new TextDesc("Nesting" + Environment.NewLine + "Depth", new Point(10, 350))); ani.Add(new LineSegmentDesc(new Point(0, 30).Sweep(new Vector(10000, 0)), Brushes.Black, 1)); ani.Add(new LineSegmentDesc(new Point(0, 100).Sweep(new Vector(10000, 0)), Brushes.Black, 1)); ani.Add(new LineSegmentDesc(new Point(0, 300).Sweep(new Vector(10000, 0)), Brushes.Black, 1)); ani.Add(new LineSegmentDesc(new Point(75, 0).Sweep(new Vector(0, 10000)), Brushes.Black, 1)); var i = 0.0; var dealloced = new HashSet<int>(); for (var i2 = 0; i2 < renderInterval.Length; i2++) { if (i2 + renderInterval.Offset < targetInterval.Offset || i2 + renderInterval.Offset >= targetInterval.Offset + targetInterval.Length) { dealloced.Add(i2 + renderInterval.Offset); } } var x = 100; var y = 90; Func<double, Animation> addFrame = focus => { var roots = keyNodes.Select(e => NestingDepthTreeNode.RootOf(e.Value.Item1)).Distinct().ToArray(); var a = new Animation(); var s = 10; if (!double.IsNaN(focus) && !double.IsInfinity(focus)) { var dx = focus - renderInterval.Offset; a.Add(new LineSegmentDesc(new LineSegment(new Point(x + dx*s, 0), new Point(x + dx*s, 10000)), activeOperation.Interval.HasValue ? Brushes.Green : Brushes.Red, 1, 1.0)); } foreach (var r in roots) a.Add(RenderTree(renderInterval, r, dealloced)); ani.LimitedNewTime(i.Seconds(), (i + dt).Seconds()).Add(a); i += dt; var bb = 0; foreach (var e in keyNodes) { Brush brush; if (e.Key == activeOperation.Key && !double.IsInfinity(focus)) { brush = activeOperation.Interval.HasValue ? Brushes.Green : Brushes.Red; } else { brush = Brushes.Yellow; } var inv = e.Value.Item2; var dx = inv.Offset - renderInterval.Offset; a.Add(new RectDesc(new Rect(x + dx * s, y - (bb+1) * s*1.1, s*inv.Length, s), fill: brush, stroke: Brushes.Black, strokeThickness: 1)); bb += 1; } return a; }; foreach (var e in operations) { activeOperation = e; var affectedRoot = e.Interval.HasValue ? keyNodes.Select(n => NestingDepthTreeNode.RootOf(n.Value.Item1)).FirstOrDefault(n => NestingDepthTreeNode.GetInterval(n).Overlaps(e.Interval.Value)) : NestingDepthTreeNode.RootOf(keyNodes[e.Key].Item1); if (e.Interval.HasValue) { keyNodes.Add(e.Key, Tuple.Create((NestingDepthTreeNode)null, e.Interval.Value, (NestingDepthTreeNode)null)); addFrame(double.NaN); addFrame(e.Interval.Value.Offset); var a1 = NestingDepthTreeNode.Include(affectedRoot, e.Interval.Value.Offset, +1, +1); a1.AdjustedNode._fakeRefCount += 2; keyNodes[e.Key] = Tuple.Create(a1.AdjustedNode, e.Interval.Value, (NestingDepthTreeNode)null); addFrame(e.Interval.Value.Offset); addFrame(e.Interval.Value.Offset + e.Interval.Value.Length); var a2 = NestingDepthTreeNode.Include(a1.NewRoot, e.Interval.Value.Offset + e.Interval.Value.Length, -1, +1); a2.AdjustedNode._fakeRefCount += 2; keyNodes[e.Key] = Tuple.Create(a1.AdjustedNode, e.Interval.Value, a2.AdjustedNode); addFrame(e.Interval.Value.Offset + e.Interval.Value.Length); addFrame(double.PositiveInfinity); } else { var xs = keyNodes[e.Key]; var r = NestingDepthTreeNode.RootOf(xs.Item1); r = NestingDepthTreeNode.Include(r, xs.Item2.Offset + xs.Item2.Length, +1, 0).NewRoot; r = NestingDepthTreeNode.Include(r, xs.Item2.Offset, -1, 0).NewRoot; var hh = new HashSet<int>(); foreach (var ex in NestingDepthTreeNode.FindHolesIn(NestingDepthTreeNode.GetInterval(r), r)) { for (var ii = ex.Offset; ii < ex.Offset + ex.Length; ii++) { hh.Add(ii); } } r = NestingDepthTreeNode.Include(r, xs.Item2.Offset + xs.Item2.Length, -1, 0).NewRoot; r = NestingDepthTreeNode.Include(r, xs.Item2.Offset, +1, 0).NewRoot; xs.Item3._fakeRefCount -= 1; xs.Item3._fakeRefCount -= 1; xs.Item1._fakeRefCount -= 1; addFrame(xs.Item2.Offset + xs.Item2.Length); var r1 = NestingDepthTreeNode.Include(r, xs.Item2.Offset + xs.Item2.Length, +1, -1); addFrame(xs.Item2.Offset + xs.Item2.Length); xs.Item1._fakeRefCount -= 1; addFrame(xs.Item2.Offset); var r2 = NestingDepthTreeNode.Include(r1.NewRoot, xs.Item2.Offset, -1, -1); keyNodes.Remove(e.Key); addFrame(double.NaN); foreach (var xxx in hh) { dealloced.Add(xxx); } NestingDepthTreeNode.PartitionAroundHoles(r2.NewRoot); addFrame(double.NaN); } } var xx = new Animation(); xx.Periodic(i.Seconds()).Add(ani); return xx; }
private static Animation RenderTree(Interval renderInterval, NestingDepthTreeNode root, HashSet<int> dealloced) { var v = renderInterval; var ani = new Animation(); var r = 10; var query = new Dictionary<int, int>(); var x = 100; var y = 350; for (var i = 0; i < v.Length; i++) { var h = NestingDepthTreeNode.QueryNestingDepthAt(root, i+v.Offset); query[i+v.Offset] = h; if (h== -1) throw new Exception(); ani.Add(new RectDesc(new Rect(x + i * r, y - h * r - 1, r, h * r + 1), fill: Brushes.Black, stroke: Brushes.Black, strokeThickness: 0)); if (dealloced.Contains(i+v.Offset)) { ani.Add(new RectDesc(new Rect(x + i * r, y - 0.5 * r - 1, r, 1 * r + 1), fill: Brushes.Red, stroke: Brushes.Orange, strokeThickness: 1)); } } var y2 = 125; Action<NestingDepthTreeNode, int> paintNode = null; paintNode = (n, l) => { if (n == null) return; var p = new Point(x + (n._offset-v.Offset)*r, y2 + l*r*5); if (n._parent != null) { var q = new Point(x + (n._parent._offset - v.Offset) * r, y2 + (l - 1) * r * 5); var b1 = false; var b2 = false; for (var i = Math.Min(n._offset, n._parent._offset); i < Math.Max(n._offset, n._parent._offset); i++) { b1 |= query[i] != 0; b2 |= query[i] == 0; } ani.Add(new LineSegmentDesc(new LineSegment(p, q), b1 && b2 ? Brushes.Red : b2 ? Brushes.Red : Brushes.Black, 1)); } if (n._less != null) paintNode(n._less, l + 1); if (n._more != null) paintNode(n._more, l + 1); ani.Add(new RectDesc(new Rect(new Point(p.X - 18, p.Y - 22), new Size(36, 44)), n._fakeRefCount > 1 ? Brushes.Black : Brushes.Red, n._fakeRefCount > 0 ? Brushes.Gray : Brushes.Red, 1)); var s = "d=" + n._adjust +Environment.NewLine + "t=" + n._subTreeTotalAdjust + Environment.NewLine + "m=" + n._subTreeRelativeMinimum; ani.Add(new TextDesc(s, new Point(p.X - 16, p.Y - 20), new Point(0, 0))); //var s = (n._adjust > 0 ? "+" : "") + n._adjust; //ani.Add(new PointDesc(p, n._fakeRefCount > 1 ? Brushes.Black : Brushes.Red, n._fakeRefCount > 0 ? Brushes.Gray : Brushes.Red, 15, 1)); //ani.Add(new TextDesc(s, new Point(p.X - 8, p.Y - 8), new Point(0, 0))); }; paintNode(root, 0); return ani; }