示例#1
0
        /// <summary>
        /// Non recursively remove constants:
        ///     A * 1 = A
        ///     A + 0 = A
        ///     A # 0 = A
        ///     A # 1 = !A
        ///     A * 0 = 0
        ///     A + 1 = 1
        /// </summary>
        public static OpCode RemoveConstNR(OpCodeMath op,
                                           ref int removeConst,
                                           ref int removeConstExpr,
                                           ref int removeUnary)
        {
            // Remove all constants
            Type opType = op.GetType();

            for (int i = 0; i < op.Operands.Count; i++)
            {
                // Must leave atleast one operand to know the value
                if (op.Operands.Count <= 1)
                {
                    break;
                }

                // Skip non-constant values
                OpCodeConst constTerm = op.Operands[i] as OpCodeConst;
                if (constTerm == null)
                {
                    continue;         // Skip non-constants
                }
                constTerm.Eval(true); // Ensure Negate is not set
                if (constTerm.State != OpState.Zero && constTerm.State != OpState.One)
                {
                    continue; // Skip non-boolean states
                }
                // Remove constant:
                //      A * 1 = A
                //      A + 0 = A
                //      A # 0 = A
                //      A # 1 = !A
                if (opType == typeof(OpCodeXor) ||
                    opType == typeof(OpCodeAnd) && constTerm.State == OpState.One ||
                    opType == typeof(OpCodeOr) && constTerm.State == OpState.Zero)
                {
                    // Check for (A # 1) = !A
                    if (opType == typeof(OpCodeXor) && constTerm.State == OpState.One)
                    {
                        op.Negate ^= OpState.One;
                    }

                    // Remove constant
                    op.Operands.RemoveAt(i);
                    i--;      // Retry this operand
                    removeConst++;
                    continue; // Continue processing all operands
                }

                // Remove constant:
                //	    A * 0 = 0
                //	    A + 1 = 1
                if (opType == typeof(OpCodeAnd) && constTerm.State == OpState.Zero ||
                    opType == typeof(OpCodeOr) && constTerm.State == OpState.One)
                {
                    // Remove entire sub-expression
                    op.Operands.Clear();
                    op.Operands.Add(constTerm);
                    removeConstExpr++;
                    break; // Done with all processing
                }
            }

            // Check for only one operand
            if (op.Operands.Count == 1)
            {
                // Remove this gate, and return the operand.
                // AND, OR, XOR = nop.  NAND, NOR, XNOR = inverter.
                removeUnary++;
                op.Operands[0].Negate ^= op.Negate;
                return(op.Operands[0]);
            }
            return(op);
        }
示例#2
0
        /// <summary>
        /// Recursively remove extraneuous levels of parenthises:
        ///	    a+(b+c) = a+b+c			Associative
        ///	    a*(b*c) = a*b*c
        ///	    a#(b#c) = a#b#c
        ///	    a#!(b#c) = !(a#b#c)
        ///	    a+!(b*c) = a+!b+!c		Demorgan's law
        ///	    a*!(b+c) = a*!b*!c
        ///	    Remove constants
        ///	    Remove identity
        ///	Same for # and *
        /// </summary>
        public OpCode Flatten(OpCode op)
        {
            OpCodeMath math = op as OpCodeMath;

            if (math == null)
            {
                return(op);
            }
            Type opType = op.GetType();

            if (opType != typeof(OpCodeAnd) &&
                opType != typeof(OpCodeOr) &&
                opType != typeof(OpCodeXor))
            {
                return(op);
            }

            // Flatten all sub-trees first
            for (int i = 0; i < math.Operands.Count; i++)
            {
                math.Operands[i] = Flatten(math.Operands[i]);
            }

            // Flatten this branch
            for (int i = 0; i < math.Operands.Count; i++)
            {
                OpCodeMath newMath = math.Operands[i] as OpCodeMath;
                if (newMath == null)
                {
                    continue;
                }

                // Associative:
                //      a+(b+c) = a+b+c
                //      a*(b*c) = a*b*c
                //      a#(b#c) = a#b#c
                //      a#!(b#c) = !(a#b#c)
                if (newMath.GetType() == opType && // Op codes must be same
                    (newMath.Negate == OpState.Zero ||
                     newMath.Negate == OpState.One && newMath is OpCodeXor))
                {
                    math.Operands.RemoveAt(i);
                    math.Operands.AddRange(newMath.Operands);
                    math.Negate ^= newMath.Negate;
                    mAssociative++;
                    i--;  // Retry this operand
                    continue;
                }

                // Demorgan's law:
                //      a+!(b*c) = a+!b+!c		Demorgan's law
                //      a*!(b+c) = a*!b*!c		Demorgan's law
                if (newMath.Negate == OpState.One)
                {
                    if (op is OpCodeOr && newMath is OpCodeAnd ||
                        op is OpCodeAnd && newMath is OpCodeOr)
                    {
                        math.Operands.RemoveAt(i);
                        foreach (OpCode newOp in newMath.Operands)
                        {
                            // Perform demorgans law (negate each sub-op code)
                            newOp.Negate ^= OpState.One;
                            math.Operands.Add(newOp);
                        }
                        mDemorgans++;
                        i--;  // Retry this operand
                        continue;
                    }
                }
            }
            return(RemoveIdentityNR(RemoveConstNR(math, ref mRemoveConst, ref mRemoveConstExpr, ref mRemoveUnary)));
        }