Beispiel #1
0
        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);
        }
Beispiel #2
0
 // 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;
 }
Beispiel #3
0
 // 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;
 }
Beispiel #4
0
        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));
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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));
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        // 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);
        }
Beispiel #10
0
        // 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);
        }
Beispiel #11
0
        // 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);
        }
Beispiel #12
0
        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;
        }
Beispiel #13
0
 // 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;
 }
Beispiel #14
0
 // 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;
 }
Beispiel #15
0
 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;
 }
Beispiel #16
0
 // 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;
 }