Beispiel #1
0
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder("StateUpdate: PrevKey=" + this._prevKey_Regular + "; NextKey=" + this.NextKey + " ");

            if (this.Empty)
            {
                sb.AppendLine("Empty UpdateState");
            }
            if (this.Reset)
            {
                sb.AppendLine("Reset UpdateState");
            }

            foreach (Flags flag in this._tools.StateConfig.GetFlagOn())
            {
                BoolExpr b = this.Get_Raw_Private(flag, true);
                if (b != null)
                {
                    sb.AppendLine(flag + ": " + ToolsZ3.ToString(b));
                }
            }
            foreach (Rn reg in this._tools.StateConfig.GetRegOn())
            {
                BoolExpr b = this.Get_Raw_Private(reg, true);
                if (b != null)
                {
                    sb.AppendLine(reg + ": " + ToolsZ3.ToString(b));
                }
            }
            if (this._branchInfo != null)
            {
                sb.AppendLine(this._branchInfo.ToString());
            }
            return(sb.ToString());
        }
Beispiel #2
0
        public string ToString2()
        {
            StringBuilder sb = new StringBuilder();

            foreach (Flags flag in this._tools.StateConfig.GetFlagOn())
            {
                BoolExpr b = this.Get_Raw_Private(flag, true);
                if (b != null)
                {
                    sb.AppendLine(flag + ": " + ToolsZ3.ToString(b));
                }
            }
            foreach (Rn reg in this._tools.StateConfig.GetRegOn())
            {
                BoolExpr b = this.Get_Raw_Private(reg, true);
                if (b != null)
                {
                    sb.AppendLine(reg + ": " + ToolsZ3.ToString(b));
                }
            }
            if (this._branchInfo != null)
            {
                sb.AppendLine(this._branchInfo.ToString());
            }
            return(sb.ToString());
        }
Beispiel #3
0
        public string ToStringConstraints(string identStr)
        {
            StringBuilder sb = new StringBuilder();

            if (this.Solver.NumAssertions > 0)
            {
                sb.AppendLine(identStr + "Current Value constraints:");
                for (int i = 0; i < (int)this.Solver.NumAssertions; ++i)
                {
                    BoolExpr e = this.Solver.Assertions[i];
                    sb.AppendLine(identStr + string.Format("   {0}: {1}", i, ToolsZ3.ToString(e)));
                }
            }
            if (this.Tools.ShowUndefConstraints)
            {
                //if (this.Solver_U.NumAssertions > 0)
                {
                    sb.AppendLine(identStr + "Current Undef constraints:");
                    for (int i = 0; i < (int)this.Solver_U.NumAssertions; ++i)
                    {
                        BoolExpr e = this.Solver_U.Assertions[i];
                        sb.AppendLine(identStr + string.Format("   {0}: {1}", i, ToolsZ3.ToString(e)));
                    }
                }
            }
            sb.AppendLine(this.BranchInfoStore.ToString());

            sb.Append("TailKey=" + this.TailKey + "; HeadKey=" + this.HeadKey);
            return(sb.ToString());
        }
Beispiel #4
0
        public Tv[] GetTvArrayMem(BitVecExpr address, int nBytes, bool addBranchInfo = true)
        {
            if (!addBranchInfo)
            {
                throw new Exception();  //TODO
            }
            this.UndefGrounding = true; // needed!

            bool popNeeded = false;

            if (addBranchInfo && (this.BranchInfoStore.Count > 0))
            {
                this.Solver.Push();
                this.Solver_U.Push();
                this.AssertBranchInfoToSolver();
                popNeeded = true;
            }

            using (BitVecExpr valueExpr = this.Create_Mem(address, nBytes))
            {
                Tv[] result = ToolsZ3.GetTvArray(valueExpr, nBytes << 3, this.Solver, this.Solver_U, this._ctx);

                if (popNeeded)
                {
                    this.Solver.Pop();
                    this.Solver_U.Pop();
                }
                return(result);
            }
        }
Beispiel #5
0
        public Tv Is_Redundant_Mem(string key1, string key2)
        {
            lock (this._ctxLock)
            {
                this.UndefGrounding = true; // needed!

                bool popNeeded = false;
                if ((this.BranchInfoStore != null) && (this.BranchInfoStore.Count > 0))
                {
                    this.Solver.Push();
                    this.Solver_U.Push();
                    this.AssertBranchInfoToSolver();
                    popNeeded = true;
                }

                using (Expr e1 = Tools.Create_Mem_Key(key1, this._ctx))
                    using (Expr e2 = Tools.Create_Mem_Key(key2, this._ctx))
                        using (BoolExpr e = this._ctx.MkEq(e1, e2))
                        {
                            Tv result = ToolsZ3.GetTv(e, e, this.Solver, this.Solver_U, this._ctx, true);
                            if (popNeeded)
                            {
                                this.Solver.Pop();
                                this.Solver_U.Pop();
                            }
                            return(result);
                        }
            }
        }
Beispiel #6
0
        public bool Is_Redundant(Rn regName, string key1, string key2)
        {
            lock (this.ctxLock_)
            {
                this.UndefGrounding = true; // needed!

                bool popNeeded = false;
                if ((this.BranchInfoStore != null) && (this.BranchInfoStore.Count > 0))
                {
                    this.Solver.Push();
                    this.Solver_U.Push();
                    this.AssertBranchInfoToSolver();
                    popNeeded = true;
                }

                using (Expr e1 = Tools.Create_Key(regName, key1, this.ctx_))
                    using (Expr e2 = Tools.Create_Key(regName, key2, this.ctx_))
                        using (BoolExpr e = this.ctx_.MkEq(e1, e2))
                        {
                            Tv result = ToolsZ3.GetTv(e, e, this.Solver, this.Solver_U, this.ctx_);

                            if (popNeeded)
                            {
                                this.Solver.Pop();
                                this.Solver_U.Pop();
                            }
                            return(result == Tv.ONE);
                        }
            }
        }
Beispiel #7
0
        private static (IList <Symbol> BoolConstants, IList <Symbol> BvConstants) GetConstants(Expr expr)
        {
            IList <Symbol> boolResults = new List <Symbol>();
            IList <Symbol> bvResults   = new List <Symbol>();

            ToolsZ3.GetConstants(expr, ref boolResults, ref bvResults);
            return(BoolConstants : boolResults, BvConstants : bvResults);
        }
Beispiel #8
0
        public static BoolExpr Create_CF_Sub(BitVecExpr a, BitVecExpr b, uint nBits, Context ctx)
        {
            BitVecExpr ax  = ctx.MkZeroExt(1, a);
            BitVecExpr bx  = ctx.MkZeroExt(1, b);
            BitVecNum  ONE = ctx.MkBV(1, 1);

            return(ToolsZ3.GetBit(ctx.MkBVSub(ax, bx), nBits, ONE, ctx));
            //return ctx.MkNot(ctx.MkBVSubNoUnderflow(a, b, false));
        }
Beispiel #9
0
        public static BoolExpr Create_CF_Add(BitVecExpr a, BitVecExpr b, uint nBits, Context ctx)
        {
            BitVecExpr ax  = ctx.MkZeroExt(1, a);
            BitVecExpr bx  = ctx.MkZeroExt(1, b);
            BitVecExpr sum = ctx.MkBVAdd(ax, bx);

            return(ToolsZ3.GetBit(sum, nBits, ctx.MkBV(1, 1), ctx));
            //return ctx.MkNot(ctx.MkBVAddNoOverflow(a, b, false));
        }
Beispiel #10
0
        public static BoolExpr Create_SF(BitVecExpr value, uint nBits, Context ctx)
        {
            Contract.Requires(value != null, "BitVecExpr value cannot be null");
            Contract.Requires(ctx != null, "Context cannot be null");
            Contract.Requires(nBits <= value.SortSize);
            Contract.Requires(nBits >= 1);
            uint bitPos = nBits - 1;

            return(ToolsZ3.GetBit(value, bitPos, ctx.MkBV(1, 1), ctx));
        }
Beispiel #11
0
        public static BitVecExpr Create_SF_BV(BitVecExpr value, uint nBits, Context ctx)
        {
            Debug.Assert(value != null, "BitVecExpr value cannot be null");
            Debug.Assert(ctx != null, "Context cannot be null");
            Debug.Assert(nBits <= value.SortSize);
            Debug.Assert(nBits >= 1);
            uint bitPos = nBits - 1;

            return(ToolsZ3.GetBit_BV(value, bitPos, ctx));
        }
Beispiel #12
0
        private string ToString(Solver solver)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("solver:");
            foreach (BoolExpr e in solver.Assertions)
            {
                sb.AppendLine(ToolsZ3.ToString(e));
            }
            return(sb.ToString());
        }
Beispiel #13
0
        private string Solver2Asm(Solver solver, Context ctx)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine("\nAsm:");
            for (int lineNumber = 1; lineNumber <= this._nLines; ++lineNumber)
            {
                string codeLine = "";
                foreach (BoolExpr instruction_Switch in this._switches[lineNumber])
                {
                    Tv tv = ToolsZ3.GetTv(instruction_Switch, solver, ctx);

                    if (false)
                    {
                        if (solver.Check() == Status.SATISFIABLE)
                        {
                            Console.WriteLine(instruction_Switch + " = " + tv);
                            Console.WriteLine(ToString(solver.Model));
                        }
                    }
                    if (tv == Tv.ONE)
                    {
                        codeLine = instruction_Switch.FuncDecl.Name.ToString();
                        break;
                    }
                    else if (tv == Tv.UNKNOWN)
                    {
                        codeLine = instruction_Switch.FuncDecl.Name + " | " + codeLine;
                    }
                }
                sb.AppendLine(codeLine);
            }
            if (false)
            {
                foreach (KeyValuePair <string, BitVecExpr> pair in this._constants)
                {
                    BitVecExpr constant = pair.Value;
                    sb.AppendLine(pair.Key + " = " + ToolsZ3.ToStringBin(ToolsZ3.GetTvArray(constant, 64, this._solver, this._ctx)));
                }

                foreach (Rn reg in new List <Rn>()
                {
                    Rn.RAX
                })                                           //, Rn.RBX, Rn.RCX, Rn.RDX})
                {
                    for (int lineNumber = 0; lineNumber <= this._nLines; ++lineNumber)
                    {
                        BitVecExpr regValue = GetReg(reg, lineNumber, ctx);
                        sb.AppendLine(regValue.FuncDecl.Name + " = " + ToolsZ3.ToStringBin(ToolsZ3.GetTvArray(regValue, 64, this._solver, this._ctx)));
                    }
                }
            }
            return(sb.ToString());
        }
Beispiel #14
0
        public Tv[] GetTvArray(Rn regName)
        {
            lock (this._ctxLock)
            {
                if (this.Frozen && this._cached_Reg_Values.TryGetValue(regName, out var value))
                {
                    return(value);
                }
                try
                {
                    this.UndefGrounding = true; // needed!

                    bool popNeeded = false;
                    if ((this.BranchInfoStore != null) && (this.BranchInfoStore.Count > 0))
                    {
                        this.Solver.Push();
                        this.Solver_U.Push();
                        this.AssertBranchInfoToSolver();
                        popNeeded = true;
                    }

                    using (BitVecExpr regExpr = this.Create(regName))
                    {
                        Tv[] result = ToolsZ3.GetTvArray(regExpr, RegisterTools.NBits(regName), this.Solver, this.Solver_U, this._ctx);

                        if (popNeeded)
                        {
                            this.Solver.Pop();
                            this.Solver_U.Pop();
                        }

                        if (this.Frozen)
                        {
                            if (ADD_COMPUTED_VALUES && (RegisterTools.NBits(regName) == 64))
                            {
                                ulong?value2 = ToolsZ3.ToUlong(result);
                                if (value2 != null)
                                {
                                    this.Solver.Assert(this.Ctx.MkEq(regExpr, this.Ctx.MkBV(value2.Value, 64)));
                                    this.Solver_Dirty = true;
                                }
                            }
                            this._cached_Reg_Values[regName] = result;
                        }
                        return(result);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("WARNING: AsmSimulator: " + e.ToString());
                    return(new Tv[RegisterTools.NBits(regName)]);
                }
            }
        }
Beispiel #15
0
        public static (BitVecExpr result, BoolExpr cf) ShiftOperations(
            Mnemonic op,
            BitVecExpr value,
            BitVecExpr nShifts,
            BoolExpr carryIn,
            string prevKey,
            Context ctx)
        {
            Contract.Requires(value != null);
            Contract.Requires(nShifts != null);
            Contract.Requires(ctx != null);
            Contract.Requires(nShifts.SortSize == 8);
            //Console.WriteLine("ShiftOperations:nShifts=" + nShifts);

            uint       nBits     = value.SortSize;
            BitVecExpr carryBV   = ctx.MkITE(carryIn, ctx.MkBV(1, 1), ctx.MkBV(0, 1)) as BitVecExpr;
            BitVecExpr nShifts65 = ctx.MkZeroExt(nBits + 1 - 8, nShifts);

            BitVecExpr value_out;
            BoolExpr   bitValue;

            switch (op)
            {
            case Mnemonic.RCR:
            {
                BitVecExpr valueWithCarry = ctx.MkConcat(carryBV, value);
                BitVecExpr rotatedValue   = ctx.MkBVRotateRight(valueWithCarry, nShifts65);
                value_out = ctx.MkExtract(nBits - 1, 0, rotatedValue);
                bitValue  = ToolsZ3.GetBit(rotatedValue, nBits, ctx.MkBV(1, 1), ctx);
            }
            break;

            case Mnemonic.RCL:
            {
                BitVecExpr valueWithCary = ctx.MkConcat(value, carryBV);
                BitVecExpr rotatedValue  = ctx.MkBVRotateLeft(valueWithCary, nShifts65);
                value_out = ctx.MkExtract(nBits, 1, rotatedValue);
                bitValue  = ToolsZ3.GetBit(rotatedValue, 0, ctx.MkBV(1, 1), ctx);
            }
            break;

            default:
                throw new Exception();
            }

            BoolExpr cf_current = Tools.Create_Key(Flags.CF, prevKey, ctx);

            BoolExpr cf = ctx.MkITE(ctx.MkEq(nShifts, ctx.MkBV(0, 8)), cf_current, bitValue) as BoolExpr;

            //Console.WriteLine("ShiftOperations:cf=" + cf);
            return(result : value_out, cf : cf);
        }
Beispiel #16
0
        public static BoolExpr Create_PF(BitVecExpr value, Context ctx)
        {
            Debug.Assert(value != null, "BitVecExpr value cannot be null");
            Debug.Assert(ctx != null, "Context cannot be null");
            BitVecExpr v01       = ctx.MkBVAdd(ToolsZ3.GetBit_BV(value, 0, ctx), ToolsZ3.GetBit_BV(value, 1, ctx));
            BitVecExpr v23       = ctx.MkBVAdd(ToolsZ3.GetBit_BV(value, 2, ctx), ToolsZ3.GetBit_BV(value, 3, ctx));
            BitVecExpr v45       = ctx.MkBVAdd(ToolsZ3.GetBit_BV(value, 4, ctx), ToolsZ3.GetBit_BV(value, 5, ctx));
            BitVecExpr v67       = ctx.MkBVAdd(ToolsZ3.GetBit_BV(value, 6, ctx), ToolsZ3.GetBit_BV(value, 7, ctx));
            BitVecExpr v0123     = ctx.MkBVAdd(v01, v23);
            BitVecExpr v4567     = ctx.MkBVAdd(v45, v67);
            BitVecExpr v01234567 = ctx.MkBVAdd(v0123, v4567);

            return(ctx.MkEq(v01234567, ctx.MkBV(0, 1)));
        }
Beispiel #17
0
 private static void CollectFlags_UNUSED(Expr e, ref Flags flags)
 {
     if (e.IsConst)
     {
         flags |= FlagTools.Parse(e.ToString().Substring(0, 2));
     }
     else
     {
         foreach (Expr e2 in e.Args)
         {
             ToolsZ3.CollectFlags_UNUSED(e2, ref flags);
         }
     }
 }
Beispiel #18
0
 /// <summary>add the contants from Expression e to the provided set</summary>
 private static void CollectConstants_UNUSED(Expr e, ref ISet <Expr> set)
 {
     if (e.IsConst)
     {
         set.Add(e);
     }
     else
     {
         foreach (Expr e2 in e.Args)
         {
             ToolsZ3.CollectConstants_UNUSED(e2, ref set);
         }
     }
 }
Beispiel #19
0
        private string ToString(Rn name, State state)
        {
            Tv[] array = state.GetTv5Array(name);
            var  tup   = ToolsZ3.HasOneValue(array);

            if (tup.hasOneValue)
            {
                return(ToolsZ3.ToStringBin(tup.value) + "");
            }
            else
            {
                return(ToolsZ3.ToStringBin(array));
            }
        }
Beispiel #20
0
        public string ToStringRegs(string identStr)
        {
            StringBuilder sb = new StringBuilder();

            foreach (Rn reg in this.Tools.StateConfig.GetRegOn())
            {
                Tv[] regContent = this.GetTvArray(reg);
                var(hasOneValue, value) = ToolsZ3.HasOneValue(regContent);
                bool showReg = !(hasOneValue && value == Tv.UNKNOWN);
                if (showReg)
                {
                    sb.Append("\n" + identStr + string.Format(reg + " = {0} = {1}", ToolsZ3.ToStringBin(regContent), ToolsZ3.ToStringHex(regContent)));
                }
            }
            return(sb.ToString());
        }
Beispiel #21
0
        public string ToStringFlags(string identStr)
        {
            StringBuilder sb = new StringBuilder();

            foreach (Flags flag in new Flags[] { Flags.CF, Flags.ZF, Flags.PF, Flags.OF, Flags.SF, Flags.AF, Flags.DF })
            {
                char c = ' ';
                if (this.Tools.StateConfig.IsFlagOn(flag))
                {
                    c = ToolsZ3.ToStringBin(this.GetTv(flag));
                }
                sb.Append(flag.ToString() + "=" + c + "; ");
            }
            sb.AppendLine("");
            return(sb.ToString());
        }
Beispiel #22
0
 public void Simplify()
 {
     lock (this._ctxLock)
     {
         if (this.Solver_Dirty)
         {
             ToolsZ3.Consolidate(false, this.Solver, this.Solver_U, this._ctx);
             this.Solver_Dirty = false;
         }
         if (this.Solver_U_Dirty)
         {
             ToolsZ3.Consolidate(true, this.Solver, this.Solver_U, this._ctx);
             this.Solver_U_Dirty = false;
         }
     }
 }
Beispiel #23
0
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            if ((this._branchInfo != null) && (this._branchInfo.Count > 0))
            {
                sb.AppendLine("Branch control flow constraints:");
                int i = 0;
                foreach (KeyValuePair <string, BranchInfo> entry in this._branchInfo)
                {
                    BoolExpr e = entry.Value.GetData(this._ctx);
                    sb.AppendLine(string.Format("   {0}: {1}", i, ToolsZ3.ToString(e)));
                    i++;
                }
            }
            return(sb.ToString());
        }
Beispiel #24
0
        public void Compress(ISet <string> keep)
        {
            ISet <string> used = new HashSet <string>(keep);

            BoolExpr[] s           = this.Solver.Assertions;
            int        nAssertions = s.Length;

            bool[] added = new bool[nAssertions];

            bool changed = true;

            while (changed)
            {
                changed = false;
                for (int i = 0; i < nAssertions; ++i)
                {
                    if (!added[i])
                    {
                        foreach (string constant in ToolsZ3.Get_Constants(s[i]))
                        {
                            if (used.Contains(constant))
                            {
                                foreach (string constant2 in ToolsZ3.Get_Constants(s[i]))
                                {
                                    used.Add(constant2);
                                }
                                added[i] = true;
                                changed  = true;
                                break;
                            }
                        }
                    }
                }
            }
            this.Solver.Reset();
            for (int i = 0; i < nAssertions; ++i)
            {
                if (added[i])
                {
                    this.Solver.Assert(s[i]);
                }
            }
        }
Beispiel #25
0
 public static Tv[] GetTvArray(BitVecExpr value, int nBits, Solver solver, Context ctx)
 {
     Tv[] results = new Tv[nBits];
     if (value == null)
     {
         Console.WriteLine("WARNING: ToolsZ3:GetTv5Array: value is null, assuming UNKNOWN");
         return(results);
     }
     using (BitVecNum bv1_1bit = ctx.MkBV(1, 1))
     {
         for (uint bit = 0; bit < nBits; ++bit)
         {
             using (BoolExpr b = ToolsZ3.GetBit(value, bit, bv1_1bit, ctx))
             {
                 results[bit] = ToolsZ3.GetTv(b, solver, ctx);
             }
         }
     }
     return(results);
 }
Beispiel #26
0
 /// <summary>Returns true if the provided valueExpr and undef yield the same tv5 array as the provided valueTv </summary>
 public static bool Equals(BitVecExpr valueExpr, BitVecExpr undef, Tv[] valueTv, int nBits, Solver solver, Solver solver_U, Context ctx)
 {
     using (BitVecNum bv1_1bit = ctx.MkBV(1, 1))
     {
         for (uint bit = 0; bit < nBits; ++bit)
         {
             using (BoolExpr b = ToolsZ3.GetBit(valueExpr, bit, bv1_1bit, ctx))
                 using (BoolExpr b_undef = ToolsZ3.GetBit(undef, bit, bv1_1bit, ctx))
                 {
                     // this can be done faster
                     Tv tv = ToolsZ3.GetTv(b, b_undef, solver, solver_U, ctx);
                     if (tv != valueTv[bit])
                     {
                         return(false);
                     }
                 }
         }
     }
     return(true);
 }
Beispiel #27
0
        public static string ToStringBin(Tv[] a)
        {
            StringBuilder sb = new StringBuilder("0b");

            if (a == null)
            {
                sb.Append("null");
            }
            else
            {
                int nBits = a.Length;
                for (int i = (nBits - 1); i >= 0; --i)
                {
                    sb.Append(ToolsZ3.ToStringBin(a[i]));
                    if ((i > 0) && (i != nBits - 1) && (i % 8 == 0))
                    {
                        sb.Append('_');
                    }
                }
            }
            return(sb.ToString());
        }
Beispiel #28
0
        public Tv GetTv(Flags flagName)
        {
            if (this.Frozen && this._cached_Flag_Values.ContainsKey(flagName))
            {
                return(this._cached_Flag_Values[flagName]);
            }
            lock (this._ctxLock)
            {
                this.UndefGrounding = true; // needed!

                bool popNeeded = false;
                if ((this.BranchInfoStore != null) && (this.BranchInfoStore.Count > 0))
                {
                    this.Solver.Push();
                    this.Solver_U.Push();
                    this.AssertBranchInfoToSolver();
                    popNeeded = true;
                }

                using (BoolExpr flagExpr = this.Create(flagName))
                {
                    Tv result = ToolsZ3.GetTv(flagExpr, flagExpr, this.Solver, this.Solver_U, this._ctx);

                    if (popNeeded)
                    {
                        this.Solver.Pop();
                        this.Solver_U.Pop();
                    }
                    if (this.Frozen)
                    {
                        this._cached_Flag_Values[flagName] = result;
                    }
                    return(result);
                }
            }
        }
Beispiel #29
0
 public void UpdateConstName(string postfix)
 {
     this.HeadKey = this.HeadKey + postfix;
     this.TailKey = this.TailKey + postfix;
     lock (this._ctxLock)
     {
         {
             BoolExpr[] content = this.Solver.Assertions;
             this.Solver.Reset();
             foreach (BoolExpr e in content)
             {
                 this.Solver.Assert(ToolsZ3.UpdateConstName(e, postfix, this._ctx) as BoolExpr);
             }
         }
         {
             BoolExpr[] content = this.Solver_U.Assertions;
             this.Solver_U.Reset();
             foreach (BoolExpr e in content)
             {
                 this.Solver_U.Assert(ToolsZ3.UpdateConstName(e, postfix, this._ctx) as BoolExpr);
             }
         }
     }
 }
Beispiel #30
0
        public static string ToStringOct(Tv[] a)
        {
            string str    = "";
            int    offset = 0;

            while (offset < a.Length)
            {
                str     = ToolsZ3.BitToCharOct(GetTv(offset), GetTv(offset + 1), GetTv(offset + 2)) + str;
                offset += 3;
                if ((offset > 0) && (offset < a.Length) && ((offset % 9) == 0))
                {
                    str = '_' + str;
                }
            }
            return("0o" + str);

            #region Local Methods
            Tv GetTv(int pos)
            {
                return(((pos < a.Length) && (pos >= 0)) ? a[pos] : Tv.ZERO);
            }

            #endregion
        }