Skip to content

Commit

Permalink
Define Comparators.ComplexNormReverseComparator for Complex values
Browse files Browse the repository at this point in the history
  • Loading branch information
axkr committed Sep 23, 2023
1 parent 20a51e9 commit 643ae1e
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
import static org.matheclipse.core.expression.F.Subtract;
import static org.matheclipse.core.expression.F.Times;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import org.apache.logging.log4j.LogManager;
Expand Down Expand Up @@ -74,7 +72,6 @@
import org.matheclipse.core.eval.util.IndexTableGenerator;
import org.matheclipse.core.expression.ASTRealMatrix;
import org.matheclipse.core.expression.ASTRealVector;
import org.matheclipse.core.expression.ComplexNum;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.expression.ImplementationStatus;
import org.matheclipse.core.expression.S;
Expand Down Expand Up @@ -2146,29 +2143,15 @@ public IExpr matrixEval(FieldMatrix<IExpr> matrix, Predicate<IExpr> zeroChecker)
return F.NIL;
}

static final class AbsReverseComparator implements Comparator<Complex> {

@Override
public final int compare(final Complex o1, final Complex o2) {
double n1 = o2.norm();
double n2 = o1.norm();
if (F.isFuzzyEquals(n1, n2, Config.DEFAULT_CHOP_DELTA)) {
return ComplexNum.compare(o1, o2);
}
return n1 < n2 ? -1 : 1;
}
}

@Override
public IAST realMatrixEval(RealMatrix matrix, EvalEngine engine) {
// TODO https://github.com/Hipparchus-Math/hipparchus/issues/174
ComplexEigenDecomposition ced = new OrderedComplexEigenDecomposition(matrix, //
ComplexEigenDecomposition.DEFAULT_EIGENVECTORS_EQUALITY, //
ComplexEigenDecomposition.DEFAULT_EPSILON, //
ComplexEigenDecomposition.DEFAULT_EPSILON_AV_VD_CHECK, //
(c1, c2) -> Double.compare(c2.norm(), c1.norm()));
Comparators.COMPLEX_NORM_REVERSE_COMPARATOR);
Complex[] eigenvalues = ced.getEigenvalues();
Arrays.sort(eigenvalues, 0, eigenvalues.length, new AbsReverseComparator());
return F.mapRange(0, eigenvalues.length, (int i) -> {
if (F.isZero(eigenvalues[i].getImaginary())) {
return F.num(eigenvalues[i].getReal());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,44 +339,11 @@ public int compareAbsValueToOne() {
}

public static int compare(final Complex c1, final Complex c2) {
if (c1.getReal() < c2.getReal()) {
return -1;
int c = Double.compare(c1.getReal(), c2.getReal());
if (c != 0) {
return c;
}
if (c1.getReal() > c2.getReal()) {
return 1;
}
long l1 = Double.doubleToLongBits(c1.getReal());
long l2 = Double.doubleToLongBits(c2.getReal());
if (l1 < l2) {
return -1;
}
if (l1 > l2) {
return 1;
}

if (F.isZero(c2.getImaginary())) {
if (!F.isZero(c1.getImaginary())) {
return 1;
}
} else if (F.isZero(c1.getImaginary())) {
return -1;
}

if (c1.getImaginary() < c2.getImaginary()) {
return -1;
}
if (c1.getImaginary() > c2.getImaginary()) {
return 1;
}
l1 = Double.doubleToLongBits(c1.getImaginary());
l2 = Double.doubleToLongBits(c2.getImaginary());
if (l1 < l2) {
return -1;
}
if (l1 > l2) {
return 1;
}
return 0;
return Double.compare(c1.getImaginary(), c2.getImaginary());
}

public int compareTo(final Complex that) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,71 @@

import java.util.Comparator;
import java.util.function.BiPredicate;
import org.hipparchus.complex.Complex;
import org.matheclipse.core.basic.Config;
import org.matheclipse.core.builtin.ListFunctions;
import org.matheclipse.core.expression.ComplexNum;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;

/** Provide <code>Comparator<IExpr></code> classes. */
public final class Comparators {

private Comparators() {}

/**
* Compares an expression with another expression for order. Returns a negative integer, zero, or
* a positive integer if this expression is canonical less than, equal to, or greater than the
* specified expression.
* Comparator for using an internal {@link BiPredicate} from
* {@link Predicates#isBinaryTrue(IExpr)} as a test for equality. If not equal call the
* <code>compareTo()
* </code> method from <code>IExpr</code>.
*/
public static final ExprComparator CANONICAL_COMPARATOR = new ExprComparator();
static final class BinaryEqualsComparator implements Comparator<IExpr> {
BiPredicate<IExpr, IExpr> predicate;

/**
* Reverse {@link #CANONICAL_COMPARATOR}, Compares an expression with another expression for
* order. Returns a negative integer, zero, or a positive integer if this expression is canonical
* greater than, equal to, or less than the specified expression.
*/
public static final ExprReverseComparator REVERSE_CANONICAL_COMPARATOR =
new ExprReverseComparator();
public BinaryEqualsComparator(IExpr test) {
this.predicate = Predicates.isBinaryTrue(test);
}

/**
* Compares the elements of two {@link IAST}s (on the first level only) until the minimum size of
* the {@link IAST}s, before considering their sequence lengths.
*/
public static final ExprLexicalComparator LEXICAL_COMPARATOR = new ExprLexicalComparator();
@Override
public int compare(IExpr e1, IExpr e2) {
if (predicate.test(e1, e2)) {
return 0;
}
return e1.compareTo(e2);
}
}

/**
* Compares an expression with another expression for order. Returns a negative integer, zero, or
* a positive integer if this expression is canonical less than, equal to, or greater than the
* specified expression.
* Compare the two {@link Complex#norm()} <code>double</code> values of the numbers. If the
* <code>norm()</code> values are approximately equal, use
* {@link ComplexNum#compare(Complex, Complex)} as the return value. Use
* {@link Config#DEFAULT_CHOP_DELTA} to compare for approcimate equality.
*/
static final class ExprComparator implements Comparator<IExpr> {
private static final class ComplexNormReverseComparator implements Comparator<Complex> {

@Override
public final int compare(final IExpr o1, final IExpr o2) {
return o1.compareTo(o2);
public final int compare(final Complex o1, final Complex o2) {
double n1 = o2.norm();
double n2 = o1.norm();
if (F.isFuzzyEquals(n1, n2, Config.DEFAULT_CHOP_DELTA)) {
return ComplexNum.compare(o1, o2);
}
return n1 < n2 ? -1 : 1;
}
}

/**
* Compares an expression with another expression for order. Returns a negative integer, zero, or
* a positive integer if this expression is canonical greater than, equal to, or less than the
* a positive integer if this expression is canonical less than, equal to, or greater than the
* specified expression.
*/
static final class ExprReverseComparator implements Comparator<IExpr> {
static final class ExprComparator implements Comparator<IExpr> {

/**
* Compares an expression with another expression for order. Returns a negative integer, zero,
* or a positive integer if this expression is canonical greater than, equal to, or less than
* the specified expression.
*/
@Override
public int compare(final IExpr o1, final IExpr o2) {
return o2.compareTo(o1);
public final int compare(final IExpr o1, final IExpr o2) {
return o1.compareTo(o2);
}
}


static final class ExprLexicalComparator implements Comparator<IExpr> {

/**
Expand Down Expand Up @@ -124,29 +127,55 @@ public int compare(final IExpr o1, final IExpr o2) {
}
}


/**
* Comparator for using an internal {@link BiPredicate} from
* {@link Predicates#isBinaryTrue(IExpr)} as a test for equality. If not equal call the
* <code>compareTo()
* </code> method from <code>IExpr</code>.
* Compares an expression with another expression for order. Returns a negative integer, zero, or
* a positive integer if this expression is canonical greater than, equal to, or less than the
* specified expression.
*/
static final class BinaryEqualsComparator implements Comparator<IExpr> {
BiPredicate<IExpr, IExpr> predicate;

public BinaryEqualsComparator(IExpr test) {
this.predicate = Predicates.isBinaryTrue(test);
}
static final class ExprReverseComparator implements Comparator<IExpr> {

/**
* Compares an expression with another expression for order. Returns a negative integer, zero,
* or a positive integer if this expression is canonical greater than, equal to, or less than
* the specified expression.
*/
@Override
public int compare(IExpr e1, IExpr e2) {
if (predicate.test(e1, e2)) {
return 0;
}
return e1.compareTo(e2);
public int compare(final IExpr o1, final IExpr o2) {
return o2.compareTo(o1);
}
}

/**
* Compares an expression with another expression for order. Returns a negative integer, zero, or
* a positive integer if this expression is canonical less than, equal to, or greater than the
* specified expression.
*/
public static final ExprComparator CANONICAL_COMPARATOR = new ExprComparator();

/**
* Reverse {@link #CANONICAL_COMPARATOR}; Compares an expression with another expression for
* order. Returns a negative integer, zero, or a positive integer if this expression is canonical
* greater than, equal to, or less than the specified expression.
*/
public static final ExprReverseComparator REVERSE_CANONICAL_COMPARATOR =
new ExprReverseComparator();

/**
* Compares the elements of two {@link IAST}s (on the first level only) until the minimum size of
* the {@link IAST}s, before considering their sequence lengths.
*/
public static final ExprLexicalComparator LEXICAL_COMPARATOR = new ExprLexicalComparator();


/**
* Compare the two {@link Complex#norm()} <code>double</code> values of the numbers. If the
* <code>norm()</code> values are approximately equal, use
* {@link ComplexNum#compare(Complex, Complex)} as the return value.
*/
public static final ComplexNormReverseComparator COMPLEX_NORM_REVERSE_COMPARATOR =
new ComplexNormReverseComparator();


/**
* Comparator for using an internal {@link BiPredicate} from
* {@link Predicates#isBinaryTrue(IExpr)} as a test for equality. If not equal call the
Expand All @@ -160,4 +189,6 @@ public static Comparator<IExpr> binaryPredicateComparator(IExpr test) {

return new BinaryEqualsComparator(test);
}

private Comparators() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20666,6 +20666,8 @@ public void testRefine() {
// check("Refine((-1)^(x+y), Element(k/2, Integers))", //
// "(-1)^y");

check("Refine(Sqrt(x^2 y^2), x>0&&y<-10)", //
"-x*y");
check("Refine(Csc(Pi*(1/2+m)), Element(m, Integers))", //
"I^(-1+2*(1/2+m))");
check("Refine(Csc(Pi*(-1/2+m)), Element(m, Integers))", //
Expand Down Expand Up @@ -22332,11 +22334,13 @@ public void testSixJSymbol() {
// "0");
// check("SixJSymbol({1, 2, 1}, {4,5,12})", //
// "0");
//

// // TODO implement for half-integers
// // check("SixJSymbol({1/2, 1/2, 1}, {5/2,7/2,3})", //
// // "SixJSymbol({1/2,1/2,1},{5/2,7/2,3})");
//
// check("SixJSymbol({1, 1, 2}, {5,7,6})", //
// "1/Sqrt(65)");
// check("SixJSymbol({1, 2, 1}, {2,3,2})", //
// "1/(5*Sqrt(21))");
// check("SixJSymbol({1, 2, 3}, {2, 1, 2})", //
Expand Down Expand Up @@ -22461,7 +22465,7 @@ public void testSort() {
check("Sort(<|a -> 4, b -> 1, c -> 3, d :> 2, e -> 2|>, Greater)", //
"<|a->4,c->3,d:>2,e->2,b->1|>");
check("Sort({2.1,1.1-I,2.1-I,I*E^(I*x)})", //
"{1.1+I*(-1.0),2.1,2.1+I*(-1.0),I*E^(I*x)}");
"{1.1+I*(-1.0),2.1+I*(-1.0),2.1,I*E^(I*x)}");
check("Sort({2,1-I,2-I,I*E^(I*x)})", //
"{1-I,2-I,2,I*E^(I*x)}");
check("Sort(StringJoin /@ Tuples({\"a\",\"A\",\"b\",\"B\"},2))", //
Expand Down

0 comments on commit 643ae1e

Please sign in to comment.