public override LifeNodeBase Next() { if (this.population == 0) { return(this.nw); } nextCalls++; if (this.next == null) { nextCacheMiss++; // If the children are leaves, we can directly calculate // the new state of the center of this node. if (this.nw.IsLeaf) { this.next = this.calcNewLeaf(); } else { // We put together 4 new nodes each half the size of this one // and designed to calculate the center half of this node. In other words, // we want to calculate the new value of this.nw.se, this.ne.sw, etc., so we // put together artificial subnodes that "wrap" nw.se, ne.sw, etc., calc their // next generation and then stick those four results together into the new child node // X X X X | X X X X // X nw nw nc | nc ne ne X // X nw nw nc | nc ne ne X // X cw cw cc | cc ce ce X // X cw cw cc | cc ce ce X // X sw sw sc | sc se se X // X sw sw sc | sc se se X // X X X X | X X X X LifeNodeBase nw = ((LifeNode)this.nw).TemporaryCenterNode(); LifeNodeBase nc = LifeNode.TemporaryCenterXNode(this.nw, this.ne); LifeNodeBase ne = ((LifeNode)this.ne).TemporaryCenterNode(); LifeNodeBase cw = LifeNode.TemporaryCenterYNode(this.nw, this.sw); LifeNodeBase cc = this.TemporaryCenterCenterNode(); LifeNodeBase ce = LifeNode.TemporaryCenterYNode(this.ne, this.se); LifeNodeBase se = ((LifeNode)this.se).TemporaryCenterNode(); LifeNodeBase sc = LifeNode.TemporaryCenterXNode(this.sw, this.se); LifeNodeBase sw = ((LifeNode)this.sw).TemporaryCenterNode(); // From those 9 temporary nodes, we construct four larger nodes and // then calculate their next generation LifeNodeBase tnw = LifeNode.CreateNode(nw, nc, cw, cc); LifeNodeBase tne = LifeNode.CreateNode(nc, ne, cc, ce); LifeNodeBase tsw = LifeNode.CreateNode(cw, cc, sw, sc); LifeNodeBase tse = LifeNode.CreateNode(cc, ce, sc, se); tnw = tnw.Next(); tne = tne.Next(); tsw = tsw.Next(); tse = tse.Next(); // Put those next gens together and we get the next gen of this node // cache it of course this.next = LifeNode.CreateNode(tnw, tne, tsw, tse); } } return(this.next); }
// ctor is private because we always want to call the factory method CreateNode, // which is the one that caches (hashes) nodes private LifeNode(LifeNodeBase nw, LifeNodeBase ne, LifeNodeBase sw, LifeNodeBase se) { // ASSERT nw, ne, sw, se are all the same dimension Debug.Assert(nw.Dimension == ne.Dimension); Debug.Assert(ne.Dimension == sw.Dimension); Debug.Assert(sw.Dimension == se.Dimension); this.dimension = nw.Dimension * 2; this.nw = nw; this.ne = ne; this.sw = sw; this.se = se; }
public static LifeNodeBase EmptySpace(int dimension) { Debug.Assert(dimension > 1); Debug.Assert(Utils.IsPowerOfTwo(dimension)); if (dimension == 2) { return(LeafLifeNode.CreateNode(0)); } LifeNodeBase next = EmptySpace(dimension / 2); return(LifeNode.CreateNode(next, next, next, next)); }
public override LifeNode ExpandUniverse() { LifeNodeBase emptySpace = LifeNode.EmptySpace(this.dimension / 2); LifeNode newNW = LifeNode.CreateNode(emptySpace, emptySpace, emptySpace, this.nw); Debug.Assert(newNW.Dimension == this.dimension); LifeNode newNE = LifeNode.CreateNode(emptySpace, emptySpace, this.ne, emptySpace); LifeNode newSW = LifeNode.CreateNode(emptySpace, this.sw, emptySpace, emptySpace); LifeNode newSE = LifeNode.CreateNode(this.se, emptySpace, emptySpace, emptySpace); LifeNode retval = LifeNode.CreateNode(newNW, newNE, newSW, newSE); Debug.Assert(retval.Dimension == dimension * 2); Debug.Assert(retval.Population == this.Population); return(retval); }
public static LifeNodeBase InitSpace(int dimension, InitLeaf initFunc) { if (!Utils.IsPowerOfTwo(dimension)) { throw new InvalidOperationException("dimension must be a power of 2"); } if (dimension == 2) { return(initFunc()); } LifeNodeBase subNode1 = LifeNode.InitSpace(dimension / 2, initFunc); LifeNodeBase subNode2 = LifeNode.InitSpace(dimension / 2, initFunc); LifeNodeBase subNode3 = LifeNode.InitSpace(dimension / 2, initFunc); LifeNodeBase subNode4 = LifeNode.InitSpace(dimension / 2, initFunc); return(LifeNode.CreateNode(subNode1, subNode2, subNode3, subNode4)); }
public static LifeNode CreateNode(LifeNodeBase nw, LifeNodeBase ne, LifeNodeBase sw, LifeNodeBase se) { LifeNode newNode = new LifeNode(nw, ne, sw, se); LifeNode cached; if (!cache.TryGetValue(newNode, out cached)) { cache.Add(newNode, newNode); misses++; } else { newNode = cached; hits++; } return(newNode); }
public LifeNodeBase TemporaryCenterCenterNode() { LifeNodeBase retval = null; if (this.NW.IsOneStepLargerThanLeaf) { bool nwbit = this.nw.SE.IsAlive(1, 1); bool nebit = this.ne.SW.IsAlive(0, 1); bool swbit = this.sw.NE.IsAlive(1, 0); bool sebit = this.se.NW.IsAlive(0, 0); retval = LeafLifeNode.CreateNode(nwbit, nebit, swbit, sebit); } else { retval = LifeNode.CreateNode(this.nw.SE.SE, this.ne.SW.SW, this.sw.NE.NE, this.se.NW.NW); } return(retval); }
// Create new LifeNode from central bits of nw, ne, sw, se public static LifeNodeBase CreateCenterNode(LifeNodeBase nw, LifeNodeBase ne, LifeNodeBase sw, LifeNodeBase se) { LifeNodeBase retval = null; if (nw.IsLeaf) { bool nwsebit = nw.IsAlive(1, 1); bool neswbit = ne.IsAlive(0, 1); bool swnebit = sw.IsAlive(1, 0); bool senwbit = se.IsAlive(0, 0); retval = LeafLifeNode.CreateNode(nwsebit, neswbit, swnebit, senwbit); } else { retval = LifeNode.CreateNode(nw.SE, ne.SW, sw.NE, se.NW); } return(retval); }
// Given two nodes, n and s, pull out these bits // XX|XX|XX|XX // XX|XX|XX|XX // XX|XX|XX|XX // XX|NW|NE|XX //------------- // XX|SW|SE|XX // XX|XX|XX|XX // XX|XX|XX|XX // XX|XX|XX|XX public static LifeNodeBase TemporaryCenterYNode(LifeNodeBase n, LifeNodeBase s) { Debug.Assert(n.Dimension == s.Dimension); LifeNodeBase retval = null; if (n.IsOneStepLargerThanLeaf) { bool nwbit = n.SW.IsAlive(1, 1); bool nebit = n.SE.IsAlive(0, 1); bool swbit = s.NW.IsAlive(1, 0); bool sebit = s.NE.IsAlive(0, 0); retval = LeafLifeNode.CreateNode(nwbit, nebit, swbit, sebit); } else { retval = LifeNode.CreateNode(n.SW.SE, n.SE.SW, s.NW.NE, s.NE.NW); } return(retval); }
// Given two nodes, w and e, pull out these bits // XX|XX|XX|XX||XX|XX|XX|XX // XX|XX|XX|NW||NE|XX|XX|XX // XX|XX|XX|SW||SE|XX|XX|XX // XX|XX|XX|XX||XX|XX|XX|XX public static LifeNodeBase TemporaryCenterXNode(LifeNodeBase w, LifeNodeBase e) { Debug.Assert(w.Dimension == e.Dimension); LifeNodeBase retval = null; if (w.IsOneStepLargerThanLeaf) { bool nwbit = w.NE.IsAlive(1, 1); bool nebit = e.NW.IsAlive(0, 1); bool swbit = w.SE.IsAlive(1, 0); bool sebit = e.SW.IsAlive(0, 0); retval = LeafLifeNode.CreateNode(nwbit, nebit, swbit, sebit); } else { retval = LifeNode.CreateNode(w.NE.SE, e.NW.SW, w.SE.NE, e.SW.NW); } return(retval); }
public override LifeNodeBase Next() { if (this.population == 0) return this.nw; nextCalls++; if (this.next == null) { nextCacheMiss++; // If the children are leaves, we can directly calculate // the new state of the center of this node. if (this.nw.IsLeaf) { this.next = this.calcNewLeaf(); } else { // We put together 4 new nodes each half the size of this one // and designed to calculate the center half of this node. In other words, // we want to calculate the new value of this.nw.se, this.ne.sw, etc., so we // put together artificial subnodes that "wrap" nw.se, ne.sw, etc., calc their // next generation and then stick those four results together into the new child node // X X X X | X X X X // X nw nw nc | nc ne ne X // X nw nw nc | nc ne ne X // X cw cw cc | cc ce ce X // X cw cw cc | cc ce ce X // X sw sw sc | sc se se X // X sw sw sc | sc se se X // X X X X | X X X X LifeNodeBase nw = ((LifeNode)this.nw).TemporaryCenterNode(); LifeNodeBase nc = LifeNode.TemporaryCenterXNode(this.nw, this.ne); LifeNodeBase ne = ((LifeNode)this.ne).TemporaryCenterNode(); LifeNodeBase cw = LifeNode.TemporaryCenterYNode(this.nw, this.sw); LifeNodeBase cc = this.TemporaryCenterCenterNode(); LifeNodeBase ce = LifeNode.TemporaryCenterYNode(this.ne, this.se); LifeNodeBase se = ((LifeNode)this.se).TemporaryCenterNode(); LifeNodeBase sc = LifeNode.TemporaryCenterXNode(this.sw, this.se); LifeNodeBase sw = ((LifeNode)this.sw).TemporaryCenterNode(); // From those 9 temporary nodes, we construct four larger nodes and // then calculate their next generation LifeNodeBase tnw = LifeNode.CreateNode(nw, nc, cw, cc); LifeNodeBase tne = LifeNode.CreateNode(nc, ne, cc, ce); LifeNodeBase tsw = LifeNode.CreateNode(cw, cc, sw, sc); LifeNodeBase tse = LifeNode.CreateNode(cc, ce, sc, se); tnw = tnw.Next(); tne = tne.Next(); tsw = tsw.Next(); tse = tse.Next(); // Put those next gens together and we get the next gen of this node // cache it of course this.next = LifeNode.CreateNode(tnw, tne, tsw, tse); } } return this.next; }
// Given two nodes, n and s, pull out these bits // XX|XX|XX|XX // XX|XX|XX|XX // XX|XX|XX|XX // XX|NW|NE|XX //------------- // XX|SW|SE|XX // XX|XX|XX|XX // XX|XX|XX|XX // XX|XX|XX|XX public static LifeNodeBase TemporaryCenterYNode(LifeNodeBase n, LifeNodeBase s) { Debug.Assert(n.Dimension == s.Dimension); LifeNodeBase retval = null; if (n.IsOneStepLargerThanLeaf) { bool nwbit = n.SW.IsAlive(1, 1); bool nebit = n.SE.IsAlive(0, 1); bool swbit = s.NW.IsAlive(1, 0); bool sebit = s.NE.IsAlive(0, 0); retval = LeafLifeNode.CreateNode(nwbit, nebit, swbit, sebit); } else { retval = LifeNode.CreateNode(n.SW.SE, n.SE.SW, s.NW.NE, s.NE.NW); } return retval; }
// Given two nodes, w and e, pull out these bits // XX|XX|XX|XX||XX|XX|XX|XX // XX|XX|XX|NW||NE|XX|XX|XX // XX|XX|XX|SW||SE|XX|XX|XX // XX|XX|XX|XX||XX|XX|XX|XX public static LifeNodeBase TemporaryCenterXNode(LifeNodeBase w, LifeNodeBase e) { Debug.Assert(w.Dimension == e.Dimension); LifeNodeBase retval = null; if (w.IsOneStepLargerThanLeaf) { bool nwbit = w.NE.IsAlive(1, 1); bool nebit = e.NW.IsAlive(0, 1); bool swbit = w.SE.IsAlive(1, 0); bool sebit = e.SW.IsAlive(0, 0); retval = LeafLifeNode.CreateNode(nwbit, nebit, swbit, sebit); } else { retval = LifeNode.CreateNode(w.NE.SE, e.NW.SW, w.SE.NE, e.SW.NW); } return retval; }
public static LifeNode CreateNode(LifeNodeBase nw, LifeNodeBase ne, LifeNodeBase sw, LifeNodeBase se) { LifeNode newNode = new LifeNode(nw, ne, sw, se); LifeNode cached; if (!cache.TryGetValue(newNode, out cached)) { cache.Add(newNode, newNode); misses++; } else { newNode = cached; hits++; } return newNode; }
// Create new LifeNode from central bits of nw, ne, sw, se public static LifeNodeBase CreateCenterNode(LifeNodeBase nw, LifeNodeBase ne, LifeNodeBase sw, LifeNodeBase se) { LifeNodeBase retval = null; if (nw.IsLeaf) { bool nwsebit = nw.IsAlive(1, 1); bool neswbit = ne.IsAlive(0, 1); bool swnebit = sw.IsAlive(1, 0); bool senwbit = se.IsAlive(0, 0); retval = LeafLifeNode.CreateNode(nwsebit, neswbit, swnebit, senwbit); } else { retval = LifeNode.CreateNode(nw.SE, ne.SW, sw.NE, se.NW); } return retval; }