Esempio n. 1
0
        public void InitializeTest()
        {
            const int loops = 10;

            Tensor x_tensor = new Tensor(Shape.Scalar(), new float[] { 0.7f });
            Tensor y_tensor = new Tensor(Shape.Scalar(), new float[] { 0.8f });

            ParameterField x = x_tensor, y = y_tensor;

            Field f = Square(x) + Square(y);
            Field g = Square(Sin(x + Sin(y))) + Square(Sin(y + Sin(x)));

            Field      loss     = f / 20 + g;
            StoreField lossnode = loss.Save();

            (Flow flow, Parameters parameters) = Flow.Optimize(loss);
            parameters.AddUpdater((parameter) => new SGD(parameter, lambda: 0.01f));

            Snapshot snapshot = parameters.Save();

            List <float> losses_first = new List <float>(), xs_first = new List <float>(), ys_first = new List <float>();

            for (int i = 0; i < loops; i++)
            {
                flow.Execute();
                parameters.Update();

                losses_first.Add(lossnode.State[0]);
                xs_first.Add(x_tensor.State[0]);
                ys_first.Add(y_tensor.State[0]);
            }

            x_tensor.State = new float[] { 0.7f };
            y_tensor.State = new float[] { 0.8f };

            parameters.InitializeUpdater();

            List <float> losses_second = new List <float>(), xs_second = new List <float>(), ys_second = new List <float>();

            for (int i = 0; i < loops; i++)
            {
                flow.Execute();
                parameters.Update();

                losses_second.Add(lossnode.State[0]);
                xs_second.Add(x_tensor.State[0]);
                ys_second.Add(y_tensor.State[0]);
            }

            CollectionAssert.AreEqual(losses_first, losses_second);
            CollectionAssert.AreEqual(xs_first, xs_second);
            CollectionAssert.AreEqual(ys_first, ys_second);

            parameters.Load(snapshot);

            List <float> losses_third = new List <float>(), xs_third = new List <float>(), ys_third = new List <float>();

            for (int i = 0; i < loops; i++)
            {
                flow.Execute();
                parameters.Update();

                losses_third.Add(lossnode.State[0]);
                xs_third.Add(x_tensor.State[0]);
                ys_third.Add(y_tensor.State[0]);
            }

            CollectionAssert.AreEqual(losses_first, losses_third);
            CollectionAssert.AreEqual(xs_first, xs_third);
            CollectionAssert.AreEqual(ys_first, ys_third);
        }
Esempio n. 2
0
        static void Train(Iterator train_iterator, MnistLoader loader, VariableField x, VariableField t, StoreField accnode, StoreField lossnode, Flow trainflow, Parameters parameters)
        {
            Stopwatch sw = new Stopwatch();

            sw.Start();

            while (train_iterator.Epoch < 50)
            {
                (float[] images, float[] labels) = loader.GetTrain(train_iterator.Next());

                x.ValueTensor.State = images;
                t.ValueTensor.State = labels;

                trainflow.Execute(enable_processing_time: true);
                parameters.Update();

                if (train_iterator.Iteration % 100 != 0)
                {
                    continue;
                }

                float train_acc  = accnode.State[0];
                float train_loss = lossnode.State[0];

                Console.WriteLine($"[{train_iterator.Iteration}] train acc: {train_acc:F3} train loss: {train_loss:E3}");
            }

            sw.Stop();

            Console.WriteLine($"{sw.ElapsedMilliseconds} msec, {sw.ElapsedMilliseconds / train_iterator.Epoch} msec/epoch");
        }
Esempio n. 3
0
 public void VisitStoreField(StoreField field)
 {
     DoAdd(field.Field.FieldType);
 }
Esempio n. 4
0
        static void Test(Iterator test_iterator, MnistLoader loader, VariableField x, VariableField t, Flow testflow, StoreField accnode)
        {
            List <float> test_acc_list = new List <float>();

            Stopwatch sw = new Stopwatch();

            sw.Start();

            while (test_iterator.Epoch < 1)
            {
                (float[] images, float[] labels) = loader.GetTest(test_iterator.Next());

                x.ValueTensor.State = images;
                t.ValueTensor.State = labels;

                testflow.Execute();

                float test_acc = accnode.State[0];

                test_acc_list.Add(test_acc);
            }

            sw.Stop();

            Console.WriteLine($"{sw.ElapsedMilliseconds} msec");

            Console.WriteLine($"[Result] acc: {test_acc_list.Average():F5}");
        }
Esempio n. 5
0
        static void Main()
        {
            const string dirpath_dataset = "mnist_dataset";
            const string dirpath_result  = "result";
            const int    classes         = 10;

            Console.WriteLine("Download mnist...");
            MnistDownloader.Download(dirpath_dataset);

            Console.WriteLine("Setup loader...");
            Random random = new Random(1234);

            MnistLoader loader         = new MnistLoader(dirpath_dataset, num_batches: 1000);
            Iterator    train_iterator = new ShuffleIterator(loader.NumBatches, loader.CountTrainDatas, random);
            Iterator    test_iterator  = new ShuffleIterator(loader.NumBatches, loader.CountTestDatas, random);

            Console.WriteLine("Create input tensor...");
            VariableField x = new Tensor(loader.BatchShape);
            VariableField t = new Tensor(Shape.Vector(loader.NumBatches));

            Console.WriteLine("Build model...");
            Field      y = CNN.Forward(x, classes);
            Field      acc = Accuracy(y, t);
            Field      err = Sum(SoftmaxCrossEntropy(y, OneHotVector(t, classes)), axes: new int[] { Axis.Map0D.Channels });
            StoreField accnode = acc.Save(), lossnode = Average(err).Save();

            Console.WriteLine("Build optimize flow...");
            (Flow trainflow, Parameters parameters) = Flow.Optimize(err);

            Console.WriteLine("Initialize params...");
            parameters
            .Where((parameter) => parameter.Category == ParameterCategory.Kernel)
            .InitializeTensor((tensor) => new HeNormal(tensor, random));
            parameters
            .Where((parameter) => parameter.Category == ParameterCategory.Bias)
            .InitializeTensor((tensor) => new Zero(tensor));

            Console.WriteLine("Set params updater...");
            parameters.AddUpdater((parameter) => new Nadam(parameter, alpha: 0.01f));
            parameters.AddUpdater((parameter) => new Ridge(parameter, decay: 1e-4f));

            Console.WriteLine("Training...");
            Train(train_iterator, loader, x, t, accnode, lossnode, trainflow, parameters);

            Console.WriteLine("Build inference flow...");
            Flow testflow = Flow.Inference(accnode);

            Console.WriteLine("Testing...");
            Test(test_iterator, loader, x, t, testflow, accnode);

            Console.WriteLine("Saving snapshot...");
            Snapshot      snapshot = parameters.Save();
            SnapshotSaver saver    = new ZippedBinaryShapshotSaver();

            if (!Directory.Exists(dirpath_result))
            {
                Directory.CreateDirectory(dirpath_result);
            }
            saver.Save($"{dirpath_result}/mnist.tss", snapshot);

            Console.WriteLine("END");
            Console.Read();
        }
Esempio n. 6
0
 protected internal virtual void VisitStoreField(StoreField node, object data)
 {
     throw new NodeNotSupportedException(node);
 }
        public void ReferenceTest()
        {
            const int elems = 4, classes = 2 + 1, boxes = 25, batches = 2;

            float[] locval = new float[elems * boxes * batches];
            float[] gtval  = new float[elems * boxes * batches];

            float[] confval  = new float[classes * boxes * batches];
            float[] labelval = new float[boxes * batches]
            {
                0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0,
                0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0
            };

            for (int i = 0; i < boxes * batches; i++)
            {
                float p = ((i % 7 + 2) * 0.123f) % 1, q = ((i % 8 + 3) * 0.213f) % 1, r = ((i % 16 + 1) * 0.231f) % 1, s = ((i % 32 + 4) * 0.523f) % 1;

                if (labelval[i] != 0)
                {
                    gtval[i * 4] = p; gtval[i * 4 + 1] = q; gtval[i * 4 + 2] = r; gtval[i * 4 + 3] = s;
                }

                locval[i * 4] = s; locval[i * 4 + 1] = p; locval[i * 4 + 2] = q; locval[i * 4 + 3] = r;

                confval[i * 3] = p / (p + r + s); confval[i * 3 + 1] = r / (p + r + s); confval[i * 3 + 2] = s / (p + r + s);
            }

            ParameterField loc  = new Tensor(Shape.Map1D(elems, boxes, batches), locval);
            ParameterField conf = new Tensor(Shape.Map1D(classes, boxes, batches), confval);

            ParameterField gt    = new Tensor(Shape.Map1D(elems, boxes, batches), gtval);
            ParameterField label = new Tensor(Shape.Map0D(boxes, batches), labelval);

            (Field locloss, Field confloss) = MultiBoxLoss(loc, gt, conf, label, hard_negative_mining_rate: 2);

            StoreField locloss_node  = locloss.Save();
            StoreField confloss_node = confloss.Save();

            (Flow flow, Parameters Parameters) = Flow.Optimize(locloss, confloss);

            flow.Execute();

            Assert.IsTrue(loc.Grad != null);
            Assert.IsTrue(conf.Grad != null);
            Assert.IsTrue(gt.Grad == null);
            Assert.IsTrue(label.Grad == null);

            float[] locloss_actual = locloss_node.Tensor.State;

            AssertError.Tolerance(locloss_expect, locloss_actual, 1e-6f, 1e-4f, $"not equal locloss");

            float[] confloss_actual = confloss_node.Tensor.State;

            AssertError.Tolerance(confloss_expect, confloss_actual, 1e-6f, 1e-4f, $"not equal confloss");

            float[] gloc_actual = loc.GradTensor.State;

            AssertError.Tolerance(gloc_expect, gloc_actual, 1e-6f, 1e-4f, $"not equal gloc");

            float[] gconf_actual = conf.GradTensor.State;

            AssertError.Tolerance(gconf_expect, gconf_actual, 1e-6f, 1e-4f, $"not equal gconf");
        }
Esempio n. 8
0
 public void WriteStoreField(StoreField s, ExpressionUsage u)
 {
     WriteStoreField(s.Source, s.Field, s.Object, s.Value, u);
 }
Esempio n. 9
0
 // ----------------------------------------------------------------------------------------
 /// <!-- ToString -->
 /// <summary>
 ///
 /// </summary>
 /// <returns></returns>
 public override string ToString()
 {
     return(StoreField.ToString() + " " + Column + "(" + InTable + ")" + " " + Length + " " + Param);
 }
Esempio n. 10
0
        public static MethodBodyBlock Convert(MethodEx method)
        {
            if (!method.IsVerified)
            {
                throw new ConvertionException();
            }
            MethodInfoExtention _method_  = new MethodInfoExtention(method.Method);
            MethodBodyBlock     mainBlock = new MethodBodyBlock(_method_.GetReturnType().type);

            mainBlock.Options["StackTypes"] = new StackTypes();
            Block currentBlock = mainBlock;

            Node[] heads = new Node[method.Count];
            Node[] tails = new Node[method.Count];
            Node   head = null;
            Node   tail = null;
            Node   firstBlock = null;
            Node   lastBlock = null;
            int    iNum, iNumNext;

            Variable[]    locals        = new Variable[method.Locals.Count];
            Variable[]    args          = new Variable[_method_.ArgCount];
            VariablesList methodVarList = mainBlock.Variables;

            for (int i = 0; i < args.Length; i++)
            {
                args[i]      = methodVarList.CreateVar(_method_.GetArgType(i).type, VariableKind.Parameter);
                args[i].Name = "Arg" + i;
//				methodVarList.Add(args[i]);
            }
            for (int i = 0; i < locals.Length; i++)
            {
                locals[i]      = methodVarList.CreateVar(method.Locals[i], VariableKind.Local);
                locals[i].Name = "Loc" + i;
//				methodVarList.Add(locals[i]);
            }

            BlockType nextBlockType;
            int       nextBlockStart = -1;
            int       nextBlockEnd   = 1 << 30;
            int       nextBlockIndex;
            Type      nextCatchBlockType;
            Hashtable tryBlocks    = new Hashtable();
            Hashtable filterBlocks = new Hashtable();
            Stack     blockEnds    = new Stack();

            blockEnds.Push(method.Count);
            FindNextBlockStart(method.EHClauses, out nextBlockType, ref nextBlockStart, ref nextBlockEnd, out nextCatchBlockType, out nextBlockIndex);

            //Nodes and blocks creation, blocks linkage
            for (iNum = 0; iNum < method.Count; iNum++)
            {
                while (iNum == (int)blockEnds.Peek())
                {
                    currentBlock = currentBlock.Parent;
                    blockEnds.Pop();
                }

                firstBlock = null;
                lastBlock  = null;
                Node thisBlock = null;
                while (iNum == nextBlockStart)
                {
                    Block currentBlockOld = currentBlock;

                    switch (nextBlockType)
                    {
                    case BlockType.Try:
                        currentBlock = new ProtectedBlock();
                        break;

                    case BlockType.Catch:
                        currentBlock = new CatchBlock(nextCatchBlockType);
                        break;

                    case BlockType.Finally:
                        currentBlock = new FinallyBlock(false);
                        break;

                    case BlockType.Filter:
                        currentBlock = new FilterBlock();
                        break;

                    case BlockType.FilteredCatch:
                        currentBlock = new UserFilteredBlock();
                        break;
                    }

                    currentBlock.setParent(currentBlockOld);

                    blockEnds.Push(nextBlockEnd);
                    if (thisBlock == null)
                    {
                        thisBlock = firstBlock = currentBlock;
                    }
                    else
                    {
                        thisBlock.Next = currentBlock;
                        thisBlock      = currentBlock;
                    }
                    switch (nextBlockType)
                    {
                    case BlockType.Try:
                        tryBlocks.Add(new Segment(nextBlockStart, nextBlockEnd), thisBlock);
                        break;

                    case BlockType.Filter:
                        filterBlocks.Add(new Segment(nextBlockStart, nextBlockEnd), thisBlock);
                        break;

                    case BlockType.Finally:
                    case BlockType.Catch:
                    {
                        Segment        tryBlockKey = FindProtectedBlock(method.EHClauses, nextBlockIndex);
                        ProtectedBlock tryBlock    = tryBlocks[tryBlockKey] as ProtectedBlock;
                        tryBlock.AddHandler(thisBlock as EHBlock);
                    }       break;

                    case BlockType.FilteredCatch:
                    {
                        Segment        tryBlockKey = FindProtectedBlock(method.EHClauses, nextBlockIndex);
                        ProtectedBlock tryBlock    = tryBlocks[tryBlockKey] as ProtectedBlock;
                        tryBlock.AddHandler(thisBlock as EHBlock);

                        Segment     filterKey   = FindFilterBlock(method.EHClauses, nextBlockIndex);
                        FilterBlock filterBlock = filterBlocks[filterKey] as FilterBlock;
                        (thisBlock as UserFilteredBlock).Filter = filterBlock;
                    }       break;
                    }
                    FindNextBlockStart(method.EHClauses, out nextBlockType, ref nextBlockStart, ref nextBlockEnd, out nextCatchBlockType, out nextBlockIndex);
                }
                lastBlock = thisBlock;

                Instruction i = method[iNum];
                switch (i.Code)
                {
                case InstructionCode.NEG:
                case InstructionCode.NOT:
                {
                    head = tail = new UnaryOp(UnaryOpFromCode(i.Code));
                    /*!*/ head.setParent(currentBlock);
                } break;

                case InstructionCode.ADD:
                case InstructionCode.AND:
                case InstructionCode.CEQ:
                case InstructionCode.CGT:
                case InstructionCode.CLT:
                case InstructionCode.DIV:
                case InstructionCode.MUL:
                case InstructionCode.OR:
                case InstructionCode.REM:
                case InstructionCode.SHL:
                case InstructionCode.SHR:
                case InstructionCode.SUB:
                case InstructionCode.XOR:
                {
                    head = tail = new BinaryOp(BinaryOpFromCode(i.Code), i.OverflowFlag, i.UnsignedFlag);
                    /*!*/ head.setParent(currentBlock);
                } break;

                case InstructionCode.LDC:
                    head = tail = new LoadConst(i.Param);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDARG:
                    head = tail = new LoadVar(args[(int)(i.Param)]);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDLOC:
                    head = tail = new LoadVar(locals[(int)(i.Param)]);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDARGA:
                    head = tail = new LoadVarAddr(args[(int)(i.Param)]);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDLOCA:
                    head = tail = new LoadVarAddr(locals[(int)(i.Param)]);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDIND:
                    head = tail = new LoadIndirect(i.TypeBySuffixOrParam());
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDFLD:
                {
                    FieldInfo field = i.Param as FieldInfo;
                    if (field.IsStatic)
                    {
                        head = new RemoveStackTop();
                        /*!*/ head.setParent(currentBlock);
                        //remove the object instance when accessing the static field with LDFLD
                        tail = new LoadField(field);
                        /*!*/ tail.setParent(currentBlock);
                        head.Next = tail;
                    }
                    else
                    {
                        head = tail = new LoadField(field);
                        /*!*/ head.setParent(currentBlock);
                    }
                }       break;

                case InstructionCode.LDFLDA:
                {
                    FieldInfo field = i.Param as FieldInfo;
                    if (field.IsStatic)
                    {
                        head = new RemoveStackTop();
                        /*!*/ head.setParent(currentBlock);
                        tail = new LoadFieldAddr(field);
                        /*!*/ tail.setParent(currentBlock);
                        head.Next = tail;
                    }
                    else
                    {
                        head = tail = new LoadFieldAddr(field);
                        /*!*/ head.setParent(currentBlock);
                    }
                }       break;

                case InstructionCode.LDSFLD:
                    head = tail = new LoadField(i.Param as FieldInfo);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDSFLDA:
                    head = tail = new LoadFieldAddr(i.Param as FieldInfo);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDELEM:
                    head = tail = new LoadElement(i.TypeBySuffixOrParam());
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDELEMA:
                    head = tail = new LoadElementAddr(i.TypeBySuffixOrParam());
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDOBJ:
                    head = tail = new LoadIndirect(i.Param as Type);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.SIZEOF:
                    head = tail = new LoadSizeOfValue(i.Param as Type);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDLEN:
                    head = tail = new LoadLength();
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDTOKEN:
                    if (i.Param is Type)
                    {
                        head = tail = new LoadConst((i.Param as Type).TypeHandle);
                    }
                    else if (i.Param is MethodBase)
                    {
                        head = tail = new LoadConst((i.Param as MethodBase).MethodHandle);
                    }
                    else if (i.Param is FieldInfo)
                    {
                        head = tail = new LoadConst((i.Param as FieldInfo).FieldHandle);
                    }
                    else
                    {
                        throw new ConvertionException();
                    }
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDNULL:
                    head = tail = new LoadConst(null);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.LDSTR:
                    head = tail = new LoadConst(i.Param);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.STARG:
                    head = tail = new StoreVar(args[(int)(i.Param)]);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.STLOC:
                    head = tail = new StoreVar(locals[(int)(i.Param)]);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.STIND:
                    head = tail = new StoreIndirect(i.TypeBySuffixOrParam());
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.STFLD:
                {
                    FieldInfo field = i.Param as FieldInfo;
                    if (field.IsStatic)
                    {
                        head = new StoreField(field);
                        /*!*/ head.setParent(currentBlock);
                        tail = new RemoveStackTop();
                        /*!*/ tail.setParent(currentBlock);
                        head.Next = tail;
                    }
                    else
                    {
                        head = tail = new StoreField(i.Param as FieldInfo);
                        /*!*/ head.setParent(currentBlock);
                    }
                }       break;

                case InstructionCode.STSFLD:
                    head = tail = new StoreField(i.Param as FieldInfo);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.STELEM:
                    head = tail = new StoreElement(i.TypeBySuffixOrParam());
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.STOBJ:
                    head = tail = new StoreIndirect(i.Param as Type);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.CPOBJ:
                    head = new LoadIndirect(i.Param as Type);
                    /*!*/ head.setParent(currentBlock);
                    tail = new StoreIndirect(i.Param as Type);
                    /*!*/ tail.setParent(currentBlock);
                    head.Next = tail;
                    break;

                case InstructionCode.DUP:
                    head = tail = new DuplicateStackTop();
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.CALL:
                    head = tail = new CallMethod(i.Param as MethodBase, false, i.HasTail);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.CALLVIRT:
                    MethodInfo callee = i.Param as MethodInfo;
                    head = tail = new CallMethod(callee, callee.IsVirtual, i.HasTail);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.NEWOBJ:
                { ConstructorInfo ctor = i.Param as ConstructorInfo;
                  if (Verifier.IsDelegate(ctor.DeclaringType))
                  {
                      if (Verifier.IsInstanceDispatch(method, iNum))
                      {
                          heads[iNum - 1] = tails[iNum - 1] = null;
                          head            = tail = new CreateDelegate(ctor, method[iNum - 1].Param as MethodInfo, false);
                      }
                      else if (Verifier.IsVirtualDispatch(method, iNum))
                      {
                          heads[iNum - 2] = tails[iNum - 2] = null;
                          heads[iNum - 1] = tails[iNum - 1] = null;
                          head            = tail = new CreateDelegate(ctor, method[iNum - 1].Param as MethodInfo, true);
                      }
                  }
                  else
                  {
                      head = tail = new NewObject(ctor);
                  }
                  /*!*/ head.setParent(currentBlock); }       break;

                case InstructionCode.NEWARR:
                    head = tail = new NewArray(i.Param as Type);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.INITOBJ:
                    head = tail = new InitValue(i.Param as Type);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.ISINST:
                    head = tail = new CastClass(i.Param as Type, false);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.CASTCLASS:
                    head = tail = new CastClass(i.Param as Type, true);
                    /*!*/ head.setParent(currentBlock);
                    break;


                case InstructionCode.BOX:
                    head = tail = new BoxValue(i.Param as Type);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.UNBOX:
                    head = tail = new UnboxValue(i.Param as Type);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.CONV:
                    head = tail = new ConvertValue(i.TypeBySuffixOrParam(), i.OverflowFlag, i.UnsignedFlag);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.POP:
                    head = tail = new RemoveStackTop();
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.BEQ:
                    head = new BinaryOp(BinaryOp.ArithOp.CEQ, false, false);
                    /*!*/ head.setParent(currentBlock);
                    tail = new Branch();
                    /*!*/ tail.setParent(currentBlock);
                    head.Next = tail;
                    break;

                case InstructionCode.BNE:
                    head = new BinaryOp(BinaryOp.ArithOp.CEQ, false, false);
                    /*!*/ head.setParent(currentBlock);
                    tail = new Branch();
                    /*!*/ tail.setParent(currentBlock);
                    head.Next = tail;
                    break;

                case InstructionCode.BGE:
                    if (TypeFixer.IsFloatOrCompatible(i.Stack.Top()))
                    {
                        head = new BinaryOp(BinaryOp.ArithOp.CLT, false, !i.UnsignedFlag);
                    }
                    else
                    {
                        head = new BinaryOp(BinaryOp.ArithOp.CLT, false, i.UnsignedFlag);
                    }
                    tail = new Branch();
                    /*!*/ head.setParent(currentBlock);
                    /*!*/ tail.setParent(currentBlock);
                    head.Next = tail;
                    break;

                case InstructionCode.BGT:
                    head = new BinaryOp(BinaryOp.ArithOp.CGT, false, i.UnsignedFlag);
                    tail = new Branch();
                    /*!*/ head.setParent(currentBlock);
                    /*!*/ tail.setParent(currentBlock);
                    head.Next = tail;
                    break;

                case InstructionCode.BLE:
                    if (TypeFixer.IsFloatOrCompatible(i.Stack.Top()))
                    {
                        head = new BinaryOp(BinaryOp.ArithOp.CGT, false, !i.UnsignedFlag);
                    }
                    else
                    {
                        head = new BinaryOp(BinaryOp.ArithOp.CGT, false, i.UnsignedFlag);
                    }
                    tail = new Branch();
                    /*!*/ head.setParent(currentBlock);
                    /*!*/ tail.setParent(currentBlock);
                    head.Next = tail;
                    break;

                case InstructionCode.BLT:
                    head = new BinaryOp(BinaryOp.ArithOp.CLT, false, i.UnsignedFlag);
                    tail = new Branch();
                    /*!*/ head.setParent(currentBlock);
                    /*!*/ tail.setParent(currentBlock);
                    head.Next = tail;
                    break;

                case InstructionCode.BRTRUE:
                    head = tail = new Branch();
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.BRFALSE:
                    head = tail = new Branch();
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.SWITCH:
                    head = tail = new Switch((i.Param as int[]).Length);
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.BR:
                case InstructionCode.NOP:
                case InstructionCode.BREAK:
                case InstructionCode.LDFTN:                             // Expecting further delegate construction...
                case InstructionCode.LDVIRTFTN:                         //
                    head = tail = new DummyNode();
                    /*!*/ head.setParent(currentBlock);
                    break;

                case InstructionCode.THROW:
                    head = tail = new ThrowException();
                    /*!*/ head.setParent(currentBlock);
                    break;


                case InstructionCode.RET:
                case InstructionCode.ENDFINALLY:
                case InstructionCode.ENDFILTER:
                case InstructionCode.LEAVE:
                    head = tail = new Leave();
                    /*!*/ head.setParent(currentBlock);
                    break;

                default:
                    throw new ConvertionException();
                }
                if (head != null)
                {
                    head.Options["StackTypes"] = i.Stack.Clone() as StackTypes;
                }
                if (head != tail)                //=>   head :: BinaryOp, tail :: Branch
                //||   head :: LoadIndirect, tail :: StoreIndirect
                {
                    if (head is BinaryOp && tail is Branch)
                    {
                        StackTypes stack = i.Stack.Clone() as StackTypes;
                        stack.Pop();
                        stack.Pop();
                        stack.Push(typeof(int));
                        tail.Options["StackTypes"] = stack;
                    }
                    else if (head is LoadIndirect && tail is StoreIndirect)
                    {
                        StackTypes stack = i.Stack.Clone() as StackTypes;
                        TypeEx     type  = stack.Pop();                    //type == S&
                        stack.Push(type.type.GetElementType());
                        tail.Options["StackTypes"] = stack;
                    }
                }
                if (firstBlock != null)
                {
                    lastBlock.Next = head;
                    for (Node n = firstBlock; n != head; n = n.Next)
                    {
                        n.Options["StackTypes"] = i.Stack.Clone() as StackTypes;
                    }
                    head = firstBlock;
                    if (tail == null)
                    {
                        tail = lastBlock;                         //This may occure what the NOP instruction starts some block
                    }
                }
                heads[iNum] = head;
                tails[iNum] = tail;
            }            //for
            mainBlock.Next = heads[0];
            //Control flow linkage
            for (iNum = 0; iNum < method.Count; iNum++)
            {
                if (heads[iNum] == null)
                {
                    throw new ConvertionException();                     //impossible :)
                }
                Instruction i = method[iNum];

                switch (i.Code)
                {
                case InstructionCode.BR:
                case InstructionCode.LEAVE:
                    tails[iNum].Next = heads[(int)i.Param];
                    break;

                case InstructionCode.RET:
                case InstructionCode.ENDFINALLY:
                case InstructionCode.ENDFILTER:
                case InstructionCode.THROW:
                case InstructionCode.RETHROW:
                    break;

                case InstructionCode.BRFALSE:                     //false
                case InstructionCode.BGE:                         //false
                case InstructionCode.BLE:                         //false
                case InstructionCode.BNE:                         //false
                    tails[iNum].Next            = heads[(int)i.Param];
                    (tails[iNum] as Branch).Alt = heads[iNum + 1];
                    break;

                case InstructionCode.BRTRUE:                      //true
                case InstructionCode.BEQ:                         //true
                case InstructionCode.BGT:                         //true
                case InstructionCode.BLT:                         //true
                    tails[iNum].Next            = heads[iNum + 1];
                    (tails[iNum] as Branch).Alt = heads[(int)i.Param];
                    break;

                case InstructionCode.SWITCH:
                    tails[iNum].Next = heads[iNum + 1];
                    Switch node = tails[iNum] as Switch;
                    int[]  alt  = i.Param as int[];
                    for (int j = 0; j < node.Count; j++)
                    {
                        node[j] = heads[alt[j]];
                    }
                    break;

                default:
                    tails[iNum].Next = heads[iNum + 1];
                    break;
                }
            }

            //Removing DummyNodes
            for (iNum = 0; iNum < method.Count; iNum++)
            {
                if (heads[iNum] is DummyNode)
                {
                    Node   dummy = heads[iNum];
                    Node[] prev  = new Node[dummy.PrevArray.Count];
                    for (int j = 0; j < prev.Length; j++)
                    {
                        prev[j] = dummy.PrevArray[j];
                    }
                    for (int j = 0; j < prev.Length; j++)
                    {
                        prev[j].NextArray[prev[j].NextArray.IndexOf(dummy)] = dummy.Next;
                    }
                    dummy.RemoveFromGraph();
                }
            }


            return(mainBlock);
        }