Quotient.java
package org.djutils.math.functions;
import java.util.Objects;
import java.util.SortedSet;
import org.djutils.exceptions.Throw;
/**
* Quotient.java.
* <p>
* Copyright (c) 2024-2025 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
* for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
* distributed under a three-clause BSD-style license, which can be found at
* <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>.
* </p>
* @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
* @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
* @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
*/
public class Quotient implements MathFunction
{
/** The numerator of this Quotient. */
private final MathFunction numerator;
/** The denominator of this Quotient. */
private final MathFunction denominator;
/**
* Construct a new Quotient; division of two <code>MathFunction</code>s, generally <code>numerator / denominator</code>.
* @param numerator the numerator part of the division (the part above the division line)
* @param denominator the denominator of the division (the part below the division line)
* @throws NullPointerException when <code>numerator</code>, or <code>denominator</code> is <code>null</code>
*/
public Quotient(final MathFunction numerator, final MathFunction denominator)
{
Throw.whenNull(numerator, "numerator");
Throw.whenNull(denominator, "denominator");
this.numerator = numerator;
this.denominator = denominator;
}
@Override
public Double apply(final Double x)
{
return this.numerator.apply(x) / this.denominator.apply(x);
}
@Override
public MathFunction getDerivative()
{
Quotient result = new Quotient(
new Sum(new Product(this.numerator.getDerivative(), this.denominator),
new Product(this.numerator.scaleBy(-1), this.denominator.getDerivative())),
new Product(this.denominator, this.denominator));
return result.simplify();
}
@Override
public MathFunction simplify()
{
if (this.denominator instanceof Constant)
{
return this.numerator.scaleBy(1.0 / this.denominator.apply(0d));
}
MathFunction divideResult = this.numerator.mergeDivide(this.denominator);
return divideResult != null ? divideResult : this;
}
@Override
public MathFunction scaleBy(final double factor)
{
return new Quotient(this.numerator.scaleBy(factor), this.denominator);
}
@Override
public int sortPriority()
{
return 102;
}
@Override
public int compareWithinSubType(final MathFunction other)
{
Throw.when(!(other instanceof Quotient), IllegalArgumentException.class, "other is of wrong type");
Quotient otherQuotient = (Quotient) other;
int result = this.denominator.compareTo(otherQuotient.denominator);
if (result != 0)
{
return result;
}
return this.numerator.compareTo(otherQuotient.numerator);
}
@Override
public KnotReport getKnotReport(final Interval<?> interval)
{
return KnotReport.UNKNOWN;
}
@Override
public SortedSet<Double> getKnots(final Interval<?> interval)
{
throw new UnsupportedOperationException(
"Cannot report knots in because I do not know where the numerator function is negative or zero");
}
@Override
public String toString()
{
StringBuilder result = new StringBuilder();
result.append("(");
result.append(this.numerator.toString());
result.append(")/(");
result.append(this.denominator.toString());
result.append(")");
return result.toString();
}
@Override
public int hashCode()
{
return Objects.hash(this.denominator, this.numerator);
}
@SuppressWarnings("checkstyle:needbraces")
@Override
public boolean equals(final Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Quotient other = (Quotient) obj;
return Objects.equals(this.denominator, other.denominator) && Objects.equals(this.numerator, other.numerator);
}
}