/// <summary> /// Compare string representations with the specific operation. /// </summary> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only comparison gives a result.</param> /// <param name="leftOperand">Left string operand to compare.</param> /// <param name="rightOperand">Right string operand to compare.</param> /// <returns>If operation is comparison, it returns boolean result, otherwise <c>null</c>.</returns> public static BooleanValue Compare(ISnapshotReadWrite snapshot, Operations operation, string leftOperand, string rightOperand) { switch (operation) { case Operations.Equal: return(snapshot.CreateBool(string.Equals(leftOperand, rightOperand, StringComparison.Ordinal))); case Operations.NotEqual: return(snapshot.CreateBool(!string.Equals(leftOperand, rightOperand, StringComparison.Ordinal))); case Operations.LessThan: return(snapshot.CreateBool(string.Compare(leftOperand, rightOperand, StringComparison.Ordinal) < 0)); case Operations.LessThanOrEqual: return(snapshot.CreateBool(string.Compare(leftOperand, rightOperand, StringComparison.Ordinal) <= 0)); case Operations.GreaterThan: return(snapshot.CreateBool(string.Compare(leftOperand, rightOperand, StringComparison.Ordinal) > 0)); case Operations.GreaterThanOrEqual: return(snapshot.CreateBool(string.Compare(leftOperand, rightOperand, StringComparison.Ordinal) >= 0)); default: return(null); } }
/// <summary> /// Compare number interval operands of the same type with the specified operation. /// </summary> /// <typeparam name="T">Comparable type of the operands.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only comparison gives a result.</param> /// <param name="leftOperand">Left number interval operand to compare.</param> /// <param name="rightOperand">Right number interval operand to compare.</param> /// <returns>If operation is comparison, it returns boolean result, otherwise <c>null</c>.</returns> public static Value IntervalCompare <T>(ISnapshotReadWrite snapshot, Operations operation, IntervalValue <T> leftOperand, IntervalValue <T> rightOperand) where T : IComparable, IComparable <T>, IEquatable <T> { switch (operation) { case Operations.Equal: return(Equal(snapshot, leftOperand, rightOperand)); case Operations.NotEqual: return(NotEqual(snapshot, leftOperand, rightOperand)); case Operations.LessThan: return(LessThan(snapshot, leftOperand, rightOperand)); case Operations.LessThanOrEqual: return(LessThanOrEqual(snapshot, leftOperand, rightOperand)); case Operations.GreaterThan: return(GreaterThan(snapshot, leftOperand, rightOperand)); case Operations.GreaterThanOrEqual: return(GreaterThanOrEqual(snapshot, leftOperand, rightOperand)); default: return(null); } }
private static Value Modulo(ISnapshotReadWrite snapshot, IntervalValue <int> leftOperand, int rightOperand) { IntervalValue <int> result; if (leftOperand.Start >= 0) { result = PositiveDividendModulo(snapshot, leftOperand.Start, leftOperand.End, rightOperand); } else { if (leftOperand.End <= 0) { result = NegativeDividendModulo(snapshot, leftOperand.Start, leftOperand.End, rightOperand); } else { var negative = NegativeDividendModulo(snapshot, leftOperand.Start, 0, rightOperand); var positive = PositiveDividendModulo(snapshot, 0, leftOperand.End, rightOperand); result = snapshot.CreateIntegerInterval(negative.Start, positive.End); } } if (result.Start < result.End) { return(result); } else { return(snapshot.CreateInt(result.Start)); } }
private static IntervalValue <int> PositiveDividendModulo(ISnapshotReadWrite snapshot, int leftOperandStart, int leftOperandEnd, int rightOperand) { if (rightOperand < 0) { if (rightOperand > int.MinValue) { rightOperand = -rightOperand; } else { return(snapshot.CreateIntegerInterval(leftOperandStart, leftOperandEnd)); } } if ((leftOperandEnd - leftOperandStart) >= rightOperand - 1) { return(snapshot.CreateIntegerInterval(0, rightOperand - 1)); } else { var resultStart = leftOperandStart % rightOperand; var resultEnd = leftOperandEnd % rightOperand; if (resultStart <= resultEnd) { return(snapshot.CreateIntegerInterval(resultStart, resultEnd)); } else { return(snapshot.CreateIntegerInterval(0, rightOperand - 1)); } } }
private static void InitalizeInternals(ISnapshotReadWrite snapshot) { if (booleanInterval == null) { booleanInterval = TypeConversion.AnyBooleanToIntegerInterval(snapshot); } }
/// <summary> /// Compare values of the same type with the specific operation. /// </summary> /// <remarks> /// Note that the method is generic and can be applied for all types that defines comparing. /// There is one exception. The string values must be compared by the specialized method, /// because default comparing of strings differs from the way the PHP compares them. /// </remarks> /// <typeparam name="T">Comparable type of the operands.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only comparison gives a result.</param> /// <param name="leftOperand">Left operand to compare.</param> /// <param name="rightOperand">Right operand to compare.</param> /// <returns>If operation is comparison, it returns boolean result, otherwise <c>null</c>.</returns> public static BooleanValue Compare <T>(ISnapshotReadWrite snapshot, Operations operation, T leftOperand, T rightOperand) where T : IComparable, IComparable <T>, IEquatable <T> { switch (operation) { case Operations.Equal: return(snapshot.CreateBool(leftOperand.Equals(rightOperand))); case Operations.NotEqual: return(snapshot.CreateBool(!leftOperand.Equals(rightOperand))); case Operations.LessThan: return(snapshot.CreateBool(leftOperand.CompareTo(rightOperand) < 0)); case Operations.LessThanOrEqual: return(snapshot.CreateBool(leftOperand.CompareTo(rightOperand) <= 0)); case Operations.GreaterThan: return(snapshot.CreateBool(leftOperand.CompareTo(rightOperand) > 0)); case Operations.GreaterThanOrEqual: return(snapshot.CreateBool(leftOperand.CompareTo(rightOperand) >= 0)); default: return(null); } }
/// <summary> /// Perform comparison of boolean values where only the right boolean operand is known. /// </summary> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only comparison gives a result.</param> /// <param name="rightOperand">Right boolean operand to compare.</param> /// <returns>If operation is comparison, it returns boolean result, otherwise <c>null</c>.</returns> public static Value LeftAbstractBooleanCompare(ISnapshotReadWrite snapshot, Operations operation, bool rightOperand) { switch (operation) { case Operations.Equal: return(snapshot.AnyBooleanValue); case Operations.NotEqual: return(snapshot.AnyBooleanValue); case Operations.LessThan: if (rightOperand) { return(snapshot.AnyBooleanValue); } else { return(snapshot.CreateBool(false)); } case Operations.LessThanOrEqual: if (rightOperand) { return(snapshot.CreateBool(true)); } else { return(snapshot.AnyBooleanValue); } case Operations.GreaterThan: if (rightOperand) { return(snapshot.CreateBool(false)); } else { return(snapshot.AnyBooleanValue); } case Operations.GreaterThanOrEqual: if (rightOperand) { return(snapshot.AnyBooleanValue); } else { return(snapshot.CreateBool(true)); } default: return(null); } }
/// <summary> /// Perform logical OR for one given boolean operand. The other is unknown. /// </summary> /// <remarks> /// It does not matter whether the concrete operand is on left or right side, /// result is the same, because logical operation is commutative. /// </remarks> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="concreteOperand">One concrete boolean operand of OR logical operation.</param> /// <returns><c>true</c> whether the operand is <c>true</c>, otherwise abstract boolean.</returns> public static Value AbstractOr(ISnapshotReadWrite snapshot, bool concreteOperand) { if (concreteOperand) { return(snapshot.CreateBool(true)); } else { return(snapshot.AnyBooleanValue); } }
/// <summary> /// Perform logical OR for one given interval operand. The other is unknown. /// </summary> /// <remarks> /// It does not matter whether the concrete operand is on left or right side, /// result is the same, because logical operation is commutative. /// </remarks> /// <typeparam name="T">Type of values in interval.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="intervalOperand">One specified interval operand of OR logical operation.</param> /// <returns><c>true</c> whether the operand is <c>true</c>, otherwise abstract boolean.</returns> public static Value AbstractOr <T>(ISnapshotReadWrite snapshot, IntervalValue <T> intervalOperand) where T : IComparable, IComparable <T>, IEquatable <T> { bool convertedValue; if (TypeConversion.TryConvertToBoolean <T>(intervalOperand, out convertedValue)) { return(AbstractOr(snapshot, convertedValue)); } else { return(snapshot.AnyBooleanValue); } }
private static IntervalValue <int> WorstModuloResult(ISnapshotReadWrite snapshot, int divisor) { Debug.Assert(divisor != 0, "Zero divisor causes modulo by zero"); if (divisor > 0) { return(snapshot.CreateIntegerInterval(1 - divisor, divisor - 1)); } else { int bound = divisor + 1; return(snapshot.CreateIntegerInterval(bound, -bound)); } }
/// <summary> /// Perform comparison of boolean values where only the right number interval operand is known. /// </summary> /// <typeparam name="T">Type of values in interval.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only comparison gives a result.</param> /// <param name="rightOperand">Right number interval operand to compare.</param> /// <returns>If operation is comparison, it returns boolean result, otherwise <c>null</c>.</returns> public static Value LeftAbstractBooleanCompare <T>(ISnapshotReadWrite snapshot, Operations operation, IntervalValue <T> rightOperand) where T : IComparable, IComparable <T>, IEquatable <T> { bool convertedValue; if (TypeConversion.TryConvertToBoolean(rightOperand, out convertedValue)) { return(LeftAbstractBooleanCompare(snapshot, operation, convertedValue)); } else { return(AbstractCompare(snapshot, operation)); } }
/// <summary> /// Perform bitwise operation for given integer and string operands. /// </summary> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only the bitwise one gives a result.</param> /// <param name="leftOperand">Left integer operand of bitwise operation.</param> /// <param name="rightOperand">Right floating-point operand of bitwise operation.</param> /// <returns>If operation is bitwise, it returns integer result, otherwise <c>null</c>.</returns> public static Value Bitwise(ISnapshotReadWrite snapshot, Operations operation, int leftOperand, double rightOperand) { int rightInteger; if (TypeConversion.TryConvertToInteger(rightOperand, out rightInteger)) { return(Bitwise(snapshot, operation, leftOperand, rightInteger)); } else { // If the right operand can not be recognized, the number can be any integer value. return(Bitwise(snapshot, operation)); } }
/// <summary> /// Perform bitwise operation for given string operands. /// </summary> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only the bitwise one gives a result.</param> /// <param name="leftOperand">Left string operand of bitwise operation.</param> /// <param name="rightOperand">Right string operand of bitwise operation.</param> /// <returns>If operation is bitwise, it returns integer result, otherwise <c>null</c>.</returns> public static Value Bitwise(ISnapshotReadWrite snapshot, Operations operation, string leftOperand, string rightOperand) { int leftInteger; if (TypeConversion.TryConvertToInteger(leftOperand, out leftInteger)) { return(Bitwise(snapshot, operation, leftInteger, rightOperand)); } else { // If the left or right operands can not be recognized, numbers can be any integer values. return(Bitwise(snapshot, operation)); } }
/// <summary> /// Perform logical XOR for given boolean and interval operands. /// </summary> /// <typeparam name="T">Type of values in interval.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="leftOperand">Left boolean operand of XOR logical operation.</param> /// <param name="rightOperand">Right interval operand of XOR logical operation.</param> /// <returns><c>true</c> whether operands are not equal, otherwise <c>false</c>.</returns> public static Value Xor <T>(ISnapshotReadWrite snapshot, bool leftOperand, IntervalValue <T> rightOperand) where T : IComparable, IComparable <T>, IEquatable <T> { bool convertedValue; if (TypeConversion.TryConvertToBoolean <T>(rightOperand, out convertedValue)) { return(snapshot.CreateBool(leftOperand != convertedValue)); } else { return(snapshot.AnyBooleanValue); } }
/// <summary> /// Perform logical XOR for given interval operands. /// </summary> /// <typeparam name="TLeft">Type of values in left interval operand.</typeparam> /// <typeparam name="TRight">Type of values in right interval operand.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="leftOperand">Left interval operand of XOR logical operation.</param> /// <param name="rightOperand">Right interval operand of XOR logical operation.</param> /// <returns><c>true</c> whether operands are not equal, otherwise <c>false</c>.</returns> public static Value Xor <TLeft, TRight>(ISnapshotReadWrite snapshot, IntervalValue <TLeft> leftOperand, IntervalValue <TRight> rightOperand) where TLeft : IComparable, IComparable <TLeft>, IEquatable <TLeft> where TRight : IComparable, IComparable <TRight>, IEquatable <TRight> { bool convertedValue; if (TypeConversion.TryConvertToBoolean <TLeft>(leftOperand, out convertedValue)) { return(Xor(snapshot, convertedValue, rightOperand)); } else { return(snapshot.AnyBooleanValue); } }
/// <summary> /// Return result of comparison operation where the left operand is greater than the right operand. /// </summary> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only comparison gives a result.</param> /// <returns>If operation is comparison, it returns boolean result, otherwise <c>null</c>.</returns> /// <seealso cref="RightAlwaysGreater"/> public static BooleanValue LeftAlwaysGreater(ISnapshotReadWrite snapshot, Operations operation) { switch (operation) { case Operations.NotEqual: case Operations.GreaterThan: case Operations.GreaterThanOrEqual: return(snapshot.CreateBool(true)); case Operations.Equal: case Operations.LessThan: case Operations.LessThanOrEqual: return(snapshot.CreateBool(false)); default: return(null); } }
/// <summary> /// Perform logical operation for one given boolean operand. The other is unknown. /// </summary> /// <remarks> /// It does not matter whether the concrete operand is on left or right side, /// result is the same, because logical operation is commutative. /// </remarks> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only the logical one gives a result.</param> /// <param name="concreteOperand">One concrete boolean operand of logical operation.</param> /// <returns>If operation is logical, it returns boolean result, otherwise <c>null</c>.</returns> public static Value AbstractLogical(ISnapshotReadWrite snapshot, Operations operation, bool concreteOperand) { switch (operation) { case Operations.And: return(AbstractAnd(snapshot, concreteOperand)); case Operations.Or: return(AbstractOr(snapshot, concreteOperand)); case Operations.Xor: return(AbstractXor(snapshot)); default: return(null); } }
/// <summary> /// Perform logical operation for given boolean operands. /// </summary> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only the logical one gives a result.</param> /// <param name="leftOperand">Left boolean operand of logical operation.</param> /// <param name="rightOperand">Right integer operand of logical operation.</param> /// <returns>If operation is logical, it returns boolean result, otherwise <c>null</c>.</returns> public static BooleanValue Logical(ISnapshotReadWrite snapshot, Operations operation, bool leftOperand, bool rightOperand) { switch (operation) { case Operations.And: return(snapshot.CreateBool(leftOperand && rightOperand)); case Operations.Or: return(snapshot.CreateBool(leftOperand || rightOperand)); case Operations.Xor: return(snapshot.CreateBool(leftOperand != rightOperand)); default: return(null); } }
/// <summary> /// Perform logical operation for given boolean and interval operands. /// </summary> /// <typeparam name="T">Type of values in interval.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only the logical one gives a result.</param> /// <param name="leftOperand">Left boolean operand of logical operation.</param> /// <param name="rightOperand">Right interval operand of logical operation.</param> /// <returns>If operation is logical, it returns boolean result, otherwise <c>null</c>.</returns> public static Value Logical <T>(ISnapshotReadWrite snapshot, Operations operation, bool leftOperand, IntervalValue <T> rightOperand) where T : IComparable, IComparable <T>, IEquatable <T> { switch (operation) { case Operations.And: return(And(snapshot, leftOperand, rightOperand)); case Operations.Or: return(Or(snapshot, leftOperand, rightOperand)); case Operations.Xor: return(Xor(snapshot, leftOperand, rightOperand)); default: return(null); } }
/// <summary> /// Perform logical operation for one given interval operand. The other is unknown. /// </summary> /// <remarks> /// It does not matter whether the concrete operand is on left or right side, /// result is the same, because logical operation is commutative. /// </remarks> /// <typeparam name="T">Type of values in interval.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only the logical one gives a result.</param> /// <param name="intervalOperand">One specified interval operand of logical operation.</param> /// <returns>If operation is logical, it returns boolean result, otherwise <c>null</c>.</returns> public static Value AbstractLogical <T>(ISnapshotReadWrite snapshot, Operations operation, IntervalValue <T> intervalOperand) where T : IComparable, IComparable <T>, IEquatable <T> { switch (operation) { case Operations.And: return(AbstractAnd(snapshot, intervalOperand)); case Operations.Or: return(AbstractOr(snapshot, intervalOperand)); case Operations.Xor: return(AbstractXor(snapshot)); default: return(null); } }
/// <summary> /// Compare whether concrete number is greater than or equal to number interval of the same type. /// </summary> /// <typeparam name="T">Comparable type of the operands.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="leftOperand">Left concrete number operand to compare.</param> /// <param name="rightOperand">Right number interval operand to compare.</param> /// <returns>Boolean value obtained by comparison of all value combinations.</returns> public static Value GreaterThanOrEqual <T>(ISnapshotReadWrite snapshot, T leftOperand, IntervalValue <T> rightOperand) where T : IComparable, IComparable <T>, IEquatable <T> { if (leftOperand.CompareTo(rightOperand.Start) >= 0) { if (leftOperand.CompareTo(rightOperand.End) >= 0) { return(snapshot.CreateBool(true)); } else { return(snapshot.AnyBooleanValue); } } else { return(snapshot.CreateBool(false)); } }
/// <summary> /// Compare concrete number to number interval of the same type for inequality. /// </summary> /// <typeparam name="T">Comparable type of the operands.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="leftOperand">Left concrete number operand to compare.</param> /// <param name="rightOperand">Right number interval operand to compare.</param> /// <returns>Boolean value obtained by comparison of all value combinations.</returns> public static Value NotEqual <T>(ISnapshotReadWrite snapshot, T leftOperand, IntervalValue <T> rightOperand) where T : IComparable, IComparable <T>, IEquatable <T> { if ((leftOperand.CompareTo(rightOperand.Start) < 0) || (leftOperand.CompareTo(rightOperand.End) > 0)) { return(snapshot.CreateBool(true)); } else { if (leftOperand.Equals(rightOperand.Start) && leftOperand.Equals(rightOperand.End)) { return(snapshot.CreateBool(false)); } else { return(snapshot.AnyBooleanValue); } } }
/// <summary> /// Perform bitwise operation for given integer operands. /// </summary> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only the bitwise one gives a result.</param> /// <param name="leftOperand">Left integer operand of bitwise operation.</param> /// <param name="rightOperand">Right integer operand of bitwise operation.</param> /// <returns>If operation is bitwise, it returns integer result, otherwise <c>null</c>.</returns> public static IntegerValue Bitwise(ISnapshotReadWrite snapshot, Operations operation, int leftOperand, int rightOperand) { switch (operation) { case Operations.BitAnd: return(snapshot.CreateInt(leftOperand & rightOperand)); case Operations.BitOr: return(snapshot.CreateInt(leftOperand | rightOperand)); case Operations.BitXor: return(snapshot.CreateInt(leftOperand ^ rightOperand)); case Operations.ShiftLeft: return(snapshot.CreateInt(leftOperand << rightOperand)); case Operations.ShiftRight: return(snapshot.CreateInt(leftOperand >> rightOperand)); default: return(null); } }
/// <summary> /// Return an abstract boolean result of XOR logical operation even if at least one operand is known. /// </summary> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <returns>An abstract boolean.</returns> public static AnyBooleanValue AbstractXor(ISnapshotReadWrite snapshot) { return(snapshot.AnyBooleanValue); }
/// <summary> /// Return an abstract boolean result of comparison when operands are unknown. /// </summary> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only comparison gives a result.</param> /// <returns>If operation is comparison, it returns any boolean, otherwise <c>null</c>.</returns> public static AnyBooleanValue AbstractCompare(ISnapshotReadWrite snapshot, Operations operation) { return(IsOperationComparison(operation) ? snapshot.AnyBooleanValue : null); }
/// <summary> /// Perform logical XOR for given interval and boolean operands. /// </summary> /// <typeparam name="T">Type of values in interval.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="leftOperand">Left interval operand of XOR logical operation.</param> /// <param name="rightOperand">Right boolean operand of XOR logical operation.</param> /// <returns><c>true</c> whether operands are not equal, otherwise <c>false</c>.</returns> public static Value Xor <T>(ISnapshotReadWrite snapshot, IntervalValue <T> leftOperand, bool rightOperand) where T : IComparable, IComparable <T>, IEquatable <T> { return(Xor(snapshot, rightOperand, leftOperand)); }
/// <summary> /// Compare whether number interval is greater than or equal to concrete number of the same type. /// </summary> /// <typeparam name="T">Comparable type of the operands.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="leftOperand">Left number interval operand to compare.</param> /// <param name="rightOperand">Right concrete number operand to compare.</param> /// <returns>Boolean value obtained by comparison of all value combinations.</returns> public static Value GreaterThanOrEqual <T>(ISnapshotReadWrite snapshot, IntervalValue <T> leftOperand, T rightOperand) where T : IComparable, IComparable <T>, IEquatable <T> { return(LessThanOrEqual(snapshot, rightOperand, leftOperand)); }
internal ToFloatConversionVisitor(ISnapshotReadWrite snapshotReadWrite) { snapshot = snapshotReadWrite; }
/// <summary> /// Return an abstract boolean result of logical operation when operands are unknown. /// </summary> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only the logical one gives a result.</param> /// <returns>If operation is logical, it returns abstract boolean, otherwise <c>null</c>.</returns> public static AnyBooleanValue AbstractLogical(ISnapshotReadWrite snapshot, Operations operation) { return(IsLogical(operation) ? snapshot.AnyBooleanValue : null); }
/// <summary> /// Perform logical operation for given interval and boolean operands. /// </summary> /// <typeparam name="T">Type of values in interval.</typeparam> /// <param name="snapshot">Read-write memory snapshot used for fix-point analysis.</param> /// <param name="operation">Operation to be performed, only the logical one gives a result.</param> /// <param name="leftOperand">Left interval operand of logical operation.</param> /// <param name="rightOperand">Right boolean operand of logical operation.</param> /// <returns>If operation is logical, it returns boolean result, otherwise <c>null</c>.</returns> public static Value Logical <T>(ISnapshotReadWrite snapshot, Operations operation, IntervalValue <T> leftOperand, bool rightOperand) where T : IComparable, IComparable <T>, IEquatable <T> { return(Logical(snapshot, operation, rightOperand, leftOperand)); }