Skip to content

Commit

Permalink
isZero()
Browse files Browse the repository at this point in the history
  • Loading branch information
mtommila committed Jan 19, 2024
1 parent ca8c97f commit 9c27809
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
/**
* Arbitrary precision calculator implementation.
*
* @version 1.11.0
* @version 1.13.0
* @author Mikko Tommila
*/

Expand Down Expand Up @@ -1305,7 +1305,7 @@ public void setInputPrecision(Long inputPrecision)
private Number fixedOrArbitraryPrecision(java.util.function.Function<Apcomplex, Apcomplex> fixedPrecisionFunction, java.util.function.Function<Apcomplex, Apcomplex> arbitraryPrecisionFunction, Number x)
{
Apcomplex z = (Apcomplex) x;
return (getInputPrecision() != null && z.real().signum() == 0 && z.imag().signum() == 0 ? fixedPrecisionFunction.apply(z) : arbitraryPrecisionFunction.apply(z));
return (getInputPrecision() != null && z.isZero() ? fixedPrecisionFunction.apply(z) : arbitraryPrecisionFunction.apply(z));
}

private FixedPrecisionApcomplexHelper fixedPrecisionApcomplexHelper = new FixedPrecisionApcomplexHelper(Apfloat.INFINITE);
Expand Down
25 changes: 19 additions & 6 deletions apfloat/src/main/java/org/apfloat/Apcomplex.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
* Copyright (c) 2002-2024 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -44,7 +44,7 @@
* @see Apfloat
* @see ApcomplexMath
*
* @version 1.12.0
* @version 1.13.0
* @author Mikko Tommila
*/

Expand Down Expand Up @@ -414,6 +414,20 @@ public long size()
return Math.max(real().size(), imag().size());
}

/**
* Returns if this number is zero.
*
* @return If this number is zero.
*
* @since 1.13.0
*/

public boolean isZero()
throws ApfloatRuntimeException
{
return real().signum() == 0 && imag().signum() == 0;
}

/**
* Returns if this number has an integer value. Note that this does not
* necessarily mean that this object is an instance of {@link Apint}.
Expand Down Expand Up @@ -504,9 +518,9 @@ public Apcomplex multiply(Apcomplex z)
public Apcomplex divide(Apcomplex z)
throws ArithmeticException, ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
throw new ArithmeticException(real().signum() == 0 && imag().signum() == 0 ? "Zero divided by zero" : "Division by zero");
throw new ArithmeticException(isZero() ? "Zero divided by zero" : "Division by zero");
}

Apfloat tmpReal,
Expand Down Expand Up @@ -773,8 +787,7 @@ public long longValueExact()
public long equalDigits(Apcomplex z)
throws ApfloatRuntimeException
{
if (real().signum() == 0 && imag().signum() == 0 &&
z.real().signum() == 0 && z.imag().signum() == 0)
if (isZero() && z.isZero())
{
// Both are zero
return Apfloat.INFINITE;
Expand Down
25 changes: 12 additions & 13 deletions apfloat/src/main/java/org/apfloat/ApcomplexMath.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public static Apcomplex pow(Apcomplex z, long n)
{
if (n == 0)
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
throw new ArithmeticException("Zero to power zero");
}
Expand Down Expand Up @@ -269,7 +269,7 @@ public static Apcomplex root(Apcomplex z, long n, long k)
{
throw new ArithmeticException("Zeroth root");
}
else if (z.real().signum() == 0 && z.imag().signum() == 0)
else if (z.isZero())
{
if (n < 0)
{
Expand Down Expand Up @@ -349,7 +349,7 @@ public static Apcomplex inverseRoot(Apcomplex z, long n)
public static Apcomplex inverseRoot(Apcomplex z, long n, long k)
throws ArithmeticException, ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
throw new ArithmeticException("Inverse root of zero");
}
Expand Down Expand Up @@ -612,7 +612,7 @@ else if (n == 0x80000000)
{
throw new ApfloatRuntimeException("Maximum array size exceeded");
}
else if (z.real().signum() == 0 && z.imag().signum() == 0)
else if (z.isZero())
{
if (n < 0)
{
Expand Down Expand Up @@ -655,8 +655,7 @@ else if (z.real().signum() == 0 && z.imag().signum() == 0)
public static Apcomplex agm(Apcomplex a, Apcomplex b)
throws ApfloatRuntimeException
{
if (a.real().signum() == 0 && a.imag().signum() == 0 ||
b.real().signum() == 0 && b.imag().signum() == 0) // Would not converge quadratically
if (a.isZero() || b.isZero()) // Would not converge quadratically
{
return Apcomplex.ZEROS[a.radix()];
}
Expand Down Expand Up @@ -908,7 +907,7 @@ else if (w.real().signum() >= 0 && w.imag().signum() == 0)
private static Apcomplex rawLog(Apcomplex z)
throws ApfloatRuntimeException
{
assert (z.real().signum() != 0 || z.imag().signum() != 0); // Infinity
assert (!z.isZero()); // Infinity

Apfloat one = new Apfloat(1, Apfloat.INFINITE, z.radix());

Expand Down Expand Up @@ -2427,7 +2426,7 @@ public static Apcomplex pochhammer(Apcomplex z, Apcomplex n)
int radix = z.radix();
long precision = Math.min(z.precision(), n.precision());
Apint one = Apint.ONES[radix];
if (n.real().signum() == 0 && n.imag().signum() == 0)
if (n.isZero())
{
return one.precision(precision);
}
Expand Down Expand Up @@ -2745,7 +2744,7 @@ public static Apcomplex hypergeometricU(Apcomplex a, Apcomplex b, Apcomplex z)
public static Apcomplex erf(Apcomplex z)
throws ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
return z;
}
Expand All @@ -2769,7 +2768,7 @@ public static Apcomplex erf(Apcomplex z)
static Apcomplex erfFixedPrecision(Apcomplex z)
throws ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
return z;
}
Expand Down Expand Up @@ -2878,7 +2877,7 @@ static Apcomplex erfiFixedPrecision(Apcomplex z)
public static Apcomplex fresnelS(Apcomplex z)
throws ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
return z;
}
Expand Down Expand Up @@ -2925,7 +2924,7 @@ public static Apcomplex fresnelS(Apcomplex z)
public static Apcomplex fresnelC(Apcomplex z)
throws ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
return z;
}
Expand Down Expand Up @@ -3040,7 +3039,7 @@ public static Apcomplex expIntegralEi(Apcomplex z)
public static Apcomplex logIntegral(Apcomplex z)
throws ArithmeticException, ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
return z;
}
Expand Down
6 changes: 3 additions & 3 deletions apfloat/src/main/java/org/apfloat/ApfloatHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -413,16 +413,16 @@ private static void checkPowPrecision(long targetPrecision)
private static Apcomplex checkPowBasic(Apcomplex z, Apcomplex w, long targetPrecision)
throws ArithmeticException, ApfloatRuntimeException
{
if (w.real().signum() == 0 && w.imag().signum() == 0)
if (w.isZero())
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
throw new ArithmeticException("Zero to power zero");
}

return new Apcomplex(new Apfloat(1, Apfloat.INFINITE, z.radix()));
}
else if (z.real().signum() == 0 && z.imag().signum() == 0)
else if (z.isZero())
{
if (w.real().signum() <= 0)
{
Expand Down
8 changes: 4 additions & 4 deletions apfloat/src/main/java/org/apfloat/BesselHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ private Apcomplex besselI(Apcomplex ν)
private Apcomplex besselFirstKind(Apcomplex ν, boolean negate)
throws ArithmeticException, ApfloatRuntimeException
{
if (ν.isInteger() && z.real().signum() == 0 && z.imag().signum() == 0)
if (ν.isInteger() && z.isZero())
{
return (ν.real().signum() == 0 ? Apint.ONES[radix] : z);
}
Expand All @@ -119,7 +119,7 @@ private Apcomplex besselFirstKind(Apcomplex ν, boolean negate)
private Apcomplex besselY()
throws ArithmeticException, ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
throw new ArithmeticException("Bessel Y of zero");
}
Expand All @@ -134,7 +134,7 @@ private Apcomplex besselY()
private Apcomplex besselK()
throws ArithmeticException, ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
throw new ArithmeticException("Bessel K of zero");
}
Expand Down Expand Up @@ -178,7 +178,7 @@ private Apcomplex besselSecondKind(BiFunction<Apcomplex, Apcomplex, Apcomplex> f

result = f.apply(ν, z);

if (result.real().signum() == 0 && result.imag().signum() == 0) // The result shouldn't be exactly zero, it means full loss of significant digits
if (result.isZero()) // The result shouldn't be exactly zero, it means full loss of significant digits
{
precisionLoss = workingPrecision;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ public Apfloat norm(Apcomplex z)
public Apcomplex acos(Apcomplex z)
throws ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
// Zero always has infinite precision so when zero input causes nonzero output special care must be taken
return halfPi(z.radix());
Expand All @@ -300,7 +300,7 @@ public Apcomplex acos(Apcomplex z)
public Apcomplex acosh(Apcomplex z)
throws ApfloatRuntimeException
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
// Zero always has infinite precision so when zero input causes nonzero output special care must be taken
return valueOf(new Apcomplex(Apfloat.ZEROS[z.radix()], halfPi(z.radix())));
Expand Down
4 changes: 2 additions & 2 deletions apfloat/src/main/java/org/apfloat/HurwitzZetaHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ public static Apcomplex zeta(Apcomplex s, Apcomplex a)
{
throw new ArithmeticException("Zeta of first argument one");
}
if (s.real().signum() == 0 && s.imag().signum() == 0 && a.real().signum() == 0 && a.imag().signum() == 0)
if (s.isZero() && a.isZero())
{
Apint two = new Apint(2, radix);
return new Aprational(one, two);
}
long precision = Math.min(s.precision(), a.precision());
if (a.isInteger() && a.real().signum() <= 0)
{
if (s.real().signum() < 0 || s.real().signum() == 0 && s.imag().signum() == 0)
if (s.real().signum() < 0 || s.isZero())
{
// Use recurrence formula: zeta(s, a) = a^-s + zeta(s, a + 1)
Apcomplex t = Apcomplex.ZERO;
Expand Down
18 changes: 9 additions & 9 deletions apfloat/src/main/java/org/apfloat/HypergeometricHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ public Apcomplex transform(Apcomplex s, Apcomplex c, Apcomplex base1, Apcomplex
term2 = pow(base2, exp2).multiply(pow(base3, exp3)).divide(gamma(g3).multiply(gamma(g4)).multiply(gamma(c2))).multiply(evaluate(a2, b2, c2, z));
}
Apcomplex d = term1.subtract(term2);
long precisionLoss = (d.real().signum() == 0 && d.imag().signum() == 0 ? workingPrecision : targetPrecision - d.precision());
long precisionLoss = (d.isZero() ? workingPrecision : targetPrecision - d.precision());
if (retry && precisionLoss > 1) // Allow a precision loss of 1 (which happens often), otherwise retry with increased precision
{
throw new RetryException(precisionLoss);
Expand Down Expand Up @@ -287,7 +287,7 @@ public Apcomplex value(Hypergeometric2F1Helper helper)
@Override
public boolean isApplicable(Apcomplex z)
{
return z.real().signum() != 0 || z.imag().signum() != 0;
return !z.isZero();
}

@Override
Expand Down Expand Up @@ -365,7 +365,7 @@ public Apcomplex value(Hypergeometric2F1Helper helper)
@Override
public boolean isApplicable(Apcomplex z)
{
return z.real().signum() != 0 || z.imag().signum() != 0;
return !z.isZero();
}

@Override
Expand Down Expand Up @@ -502,7 +502,7 @@ else if (br.compareTo(n) > 0)
Apfloat n1 = n.add(Apint.ONES[radix]);
Apcomplex[] pochhammer = Arrays.stream(a).map(ai -> ApcomplexMath.pochhammer(ai, n1)).toArray(Apcomplex[]::new);
result = ApcomplexMath.product(pochhammer);
if (result.real().signum() != 0 || result.imag().signum() != 0)
if (!result.isZero())
{
Apfloat n2 = n.add(new Apint(2, radix));
Apcomplex[] gamma = Arrays.stream(b).map(n1::add).map(this::ensureGammaPrecision).map(ApcomplexMath::gamma).toArray(Apcomplex[]::new);
Expand Down Expand Up @@ -558,7 +558,7 @@ private Apcomplex hypergeometricPFQ()
}
if (a.length > b.length + 1L)
{
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
return new Apfloat(1, targetPrecision, radix);
}
Expand Down Expand Up @@ -797,7 +797,7 @@ private Apcomplex checkResult()
{
throw new ArithmeticException("Division by zero");
}
if (z.real().signum() == 0 && z.imag().signum() == 0)
if (z.isZero())
{
return new Apfloat(1, targetPrecision, radix);
}
Expand Down Expand Up @@ -856,7 +856,7 @@ private Apcomplex evaluate(Apcomplex[] a, Apcomplex[] b, Apcomplex z)
numerator = numerator.multiply(a[j]);
a[j] = a[j].add(one);
}
if (numerator.real().signum() == 0 && numerator.imag().signum() == 0)
if (numerator.isZero())
{
return s; // It was a polynomial
}
Expand All @@ -871,9 +871,9 @@ private Apcomplex evaluate(Apcomplex[] a, Apcomplex[] b, Apcomplex z)
t = numerator.divide(denominator);
s = s.add(t);
maxSScale = Math.max(maxSScale, s.scale());
} while (i.compareTo(minN) <= 0 || divergentSeries && checkDivergence(o, t) || s.real().signum() == 0 && s.imag().signum() == 0 || s.scale() - t.scale() <= workingPrecision); // Subtraction might overflow
} while (i.compareTo(minN) <= 0 || divergentSeries && checkDivergence(o, t) || s.isZero() || s.scale() - t.scale() <= workingPrecision); // Subtraction might overflow

precisionLoss = (s.real().signum() == 0 && s.imag().signum() == 0 ? extendedPrecision : maxSScale - s.scale()); // Loss due to scale of s reduced from its peak (loss off most significant digits)
precisionLoss = (s.isZero() ? extendedPrecision : maxSScale - s.scale()); // Loss due to scale of s reduced from its peak (loss off most significant digits)
if (workingPrecision - s.precision() > 1) // Often the precision is reduced by 1
{
precisionLoss = Util.ifFinite(precisionLoss, precisionLoss + workingPrecision - s.precision()); // Loss due to accumulation (loss off least significant digits)
Expand Down

0 comments on commit 9c27809

Please sign in to comment.