Returns true iff {@code left} and {@code right} are finite values within {@code tolerance} of
each other. Note that both this method and {@link #notEqualWithinTolerance} returns false if
either {@code left} or {@code right} is infinite or NaN.
334603
public static boolean equalWithinTolerance(double left, double right, double tolerance) {
    return Math.abs(left - right) <= Math.abs(tolerance);
  }
667272
public static boolean isArrayEqual(final Object[] left, final Object[] right) {
        if (left == right) {
            return true;
        }
        if (left == null || right == null) {
            return false;
        }
        if (left.length != right.length) {
            return false;
        }
        for (int i = 0; i < left.length; ++i) {
            if (!isArrayElementEqual(left[i], right[i])) {
                return false;
            }
        }
        return true;
    }
1000612
public Object divide(Object left, Object right) {
    if (left == null && right == null) {
      return 0;
    }

    // if either are floating point (double or float) use double
    if (isFloatingPointNumber(left) || isFloatingPointNumber(right)) {
      double l = toDouble(left);
      double r = toDouble(right);
      if (r == 0.0) {
        throw new ArithmeticException("/");
      }
      return new Double(l / r);
    }

    // if either are bigdecimal use that type
    if (left instanceof BigDecimal || right instanceof BigDecimal) {
      BigDecimal l = toBigDecimal(left);
      BigDecimal r = toBigDecimal(right);
      if (BigDecimal.ZERO.equals(r)) {
        throw new ArithmeticException("/");
      }
      BigDecimal result = l.divide(r, getMathContext());
      return narrowBigDecimal(left, right, result);
    }

    // otherwise treat as integers
    BigInteger l = toBigInteger(left);
    BigInteger r = toBigInteger(right);
    if (BigInteger.ZERO.equals(r)) {
      throw new ArithmeticException("/");
    }
    BigInteger result = l.divide(r);
    return narrowBigInteger(left, right, result);
  }
1170298
public static IsEqual isEqual(ComparableExpression<Number> left, Number constant) {
        return new IsEqual(left, constant(constant));
    }
470726
public static boolean isNewerThan(final Version left, final Version right) {

	// major
	if (left.getMajor() > right.getMajor()) return true;
	if (left.getMajor() < right.getMajor()) return false;

	// minor
	if (left.getMinor() > right.getMinor()) return true;
	if (left.getMinor() < right.getMinor()) return false;

	// micro
	if (left.getMicro() > right.getMicro()) return true;
	if (left.getMicro() < right.getMicro()) return false;

	// qualifier
	// left
	String q = left.getQualifier();
	int index = q.indexOf('-');
	String qla = index == -1 ? "" : q.substring(index + 1).trim();
	String qln = index == -1 ? q : q.substring(0, index);
	int ql = isEmpty(qln) ? Integer.MIN_VALUE : Integer.parseInt(qln);

	// right
	q = right.getQualifier();
	index = q.indexOf('-');
	String qra = index == -1 ? "" : q.substring(index + 1).trim();
	String qrn = index == -1 ? q : q.substring(0, index);
	int qr = isEmpty(qln) ? Integer.MIN_VALUE : Integer.parseInt(qrn);

	if (ql > qr) return true;
	if (ql < qr) return false;

	int qlan = qualifierAppendix2Number(qla);
	int qran = qualifierAppendix2Number(qra);

	if (qlan > qran) return true;
	if (qlan < qran) return false;

	if (qlan == QUALIFIER_APPENDIX_OTHER && qran == QUALIFIER_APPENDIX_OTHER) return left.compareTo(right) > 0;

	return false;
    }
548544
public static Boolean implies(Boolean left, Boolean right) {
        return !left || Boolean.TRUE.equals(right);
    }
69438
public static Boolean gte(Object left, Object right) {
        return or(gt(left, right),
                  eq(left, right)); // do not use Java || to avoid potential NPE due to FEEL 3vl.
    }
68341
public final void acceptBoth(Consumer<? super L> left, Consumer<? super R> right, L defaultLeft, R defaultRight) {
		left.accept(isLeft() ? getLeft() : defaultLeft);
		right.accept(isRight() ? getRight() : defaultRight);
	}
154376
private Boolean compareValues(Session session, Object[] left,
                                  Object[] right) {

        int     result  = 0;
        boolean hasNull = false;

        if (left == null || right == null) {
            return null;
        }

        Object[] leftList  = left;
        Object[] rightList = right;

        for (int i = 0; i < nodes[LEFT].nodes.length; i++) {
            if (leftList[i] == null) {
                if (opType == OpTypes.MATCH_PARTIAL
                        || opType == OpTypes.MATCH_UNIQUE_PARTIAL) {
                    continue;
                }

                hasNull = true;
            }

            if (rightList[i] == null) {
                hasNull = true;
            }

            Object leftValue  = leftList[i];
            Object rightValue = rightList[i];
            Type[] types      = nodes[LEFT].nodeDataTypes;

            result = types[i].compare(leftValue, rightValue);

            if (result != 0) {
                break;
            }
        }

        switch (opType) {

            case OpTypes.MATCH_SIMPLE :
            case OpTypes.MATCH_UNIQUE_SIMPLE :
            case OpTypes.MATCH_PARTIAL :
            case OpTypes.MATCH_UNIQUE_PARTIAL :
            case OpTypes.MATCH_FULL :
            case OpTypes.MATCH_UNIQUE_FULL :
            case OpTypes.NOT_DISTINCT :
                return result == 0 ? Boolean.TRUE
                                   : Boolean.FALSE;

            case OpTypes.IN :
            case OpTypes.EQUAL :
                if (hasNull) {
                    return null;
                }

                return result == 0 ? Boolean.TRUE
                                   : Boolean.FALSE;

            case OpTypes.NOT_EQUAL :
                if (hasNull) {
                    return null;
                }

                return result != 0 ? Boolean.TRUE
                                   : Boolean.FALSE;

            case OpTypes.GREATER :
                if (hasNull) {
                    return null;
                }

                return result > 0 ? Boolean.TRUE
                                  : Boolean.FALSE;

            case OpTypes.GREATER_EQUAL :
                if (hasNull) {
                    return null;
                }

                return result >= 0 ? Boolean.TRUE
                                   : Boolean.FALSE;

            case OpTypes.SMALLER_EQUAL :
                if (hasNull) {
                    return null;
                }

                return result <= 0 ? Boolean.TRUE
                                   : Boolean.FALSE;

            case OpTypes.SMALLER :
                if (hasNull) {
                    return null;
                }

                return result < 0 ? Boolean.TRUE
                                  : Boolean.FALSE;

            default :
                throw Error.runtimeError(ErrorCode.U_S0500, "Expression");
        }
    }
566197
public static Expression compareSoyEquals(final SoyExpression left, final SoyExpression right) {
    // We can special case when we know the types.
    // If either is a string, we run special logic so test for that first
    // otherwise we special case primitives and eventually fall back to our runtime.
    SoyRuntimeType leftRuntimeType = left.soyRuntimeType();
    SoyRuntimeType rightRuntimeType = right.soyRuntimeType();
    if (leftRuntimeType.isKnownString()) {
      return doEqualsString(left.unboxAsString(), right);
    }
    if (rightRuntimeType.isKnownString()) {
      // TODO(lukes): we are changing the order of evaluation here.
      return doEqualsString(right.unboxAsString(), left);
    }
    if (leftRuntimeType.isKnownInt()
        && rightRuntimeType.isKnownInt()
        && left.isNonNullable()
        && right.isNonNullable()) {
      return compare(Opcodes.IFEQ, left.unboxAsLong(), right.unboxAsLong());
    }
    if (leftRuntimeType.isKnownNumber()
        && rightRuntimeType.isKnownNumber()
        && left.isNonNullable()
        && right.isNonNullable()
        && (leftRuntimeType.isKnownFloat() || rightRuntimeType.isKnownFloat())) {
      return compare(Opcodes.IFEQ, left.coerceToDouble(), right.coerceToDouble());
    }
    return MethodRef.RUNTIME_EQUAL.invoke(left.box(), right.box());
  }
295365
public static IsGreaterThanOrEqual isGreaterThanOrEqual(ComparableExpression<Number> left, ComparableExpression<Number> right) {
        return new IsGreaterThanOrEqual(left, right);
    }
786921
public static Boolean eq(Object left, Object right) {
        return EvalHelper.isEqual(left, right, null);
    }
700809
public boolean evaluate(InternalWorkingMemory workingMemory, Object left, Object right) {
        Object leftValue = leftTimestamp != null ? leftTimestamp : left;
        Object rightValue = rightTimestamp != null ? rightTimestamp : right;

        return rightLiteral ?
                evaluator.evaluate( workingMemory,
                                    new ConstantValueReader( leftValue ),
                                    dummyFactHandleOf( leftValue ),
                                    new ObjectFieldImpl( rightValue ) ) :
                evaluator.evaluate( workingMemory,
                                    new ConstantValueReader( leftValue ),
                                    dummyFactHandleOf( leftValue ),
                                    new ConstantValueReader( rightValue ),
                                    dummyFactHandleOf( rightValue ) );
    }
414493
private static boolean doIsAssignableFrom(Type left, Type right, boolean failOpen) {
    if (left.equals(right)) {
      return true;
    }
    if (left.getSort() != right.getSort()) {
      return false;
    }
    if (left.getSort() != Type.OBJECT) {
      return false; // all other sorts require exact equality (even arrays)
    }
    // for object types we really need to know type hierarchy information to test for whether
    // right is assignable to left.
    Optional<Class<?>> leftClass = objectTypeToClassCache.getUnchecked(left);
    Optional<Class<?>> rightClass = objectTypeToClassCache.getUnchecked(right);
    if (!leftClass.isPresent() || !rightClass.isPresent()) {
      // This means one of the types being compared is a generated object.  So we can't easily check
      // it.  Just delegate responsibility to the verifier.
      return failOpen;
    }
    return leftClass.get().isAssignableFrom(rightClass.get());
  }
1315559
private function isArrayAndInstanceOfCountable($left, $right): Bool
    {
        if (!($left instanceof Node && $right instanceof Node)) {
            return false;
        }

        if (!$this->isFunctionCall($left, 'is_array')) {
            return false;
        }
        $args = $left->children['args'];

        if ($args->kind !== \ast\AST_ARG_LIST) {
            return false;
        }
        $arg = $args->children[0];

        if ($right->kind !== \ast\AST_INSTANCEOF) {
            return false;
        }
        $expr = $right->children['expr'];
        $class = $right->children['class'];

        if ($class->kind === \ast\AST_NAME
              && $class->children['name'] === "Countable"
              && $this->isEqualsWithoutLineno($arg, $expr)) {
            return true;
        }

        return false;
    }
1091074
public static <D> Predicate in(Expression<D> left, Collection<? extends D> right) {
        if (right.size() == 1) {
            return eqConst(left, right.iterator().next());
        } else {
            return predicate(Ops.IN, left, ConstantImpl.create(right));
        }
    }
124830
@Pure /* not guaranteed, since compareTo() is invoked */
	@Inline("($1.compareTo($2) >= 0)")
	public static <C> boolean operator_greaterEqualsThan(Comparable<? super C> left, C right) {
		return left.compareTo(right) >= 0;
	}