public abstract class Scalar extends DefinitionalObject
This example shows how to create a new Scalar subclass:
// Create a new type derived from Scalar. This type will represent the square root of
// another scalar.
public static class SquareRootScalar extends Scalar {
public SquareRootScalar() {}
public SquareRootScalar(Scalar scalarToTakeSquareRootOf) {
m_scalar = scalarToTakeSquareRootOf;
}
// The copy constructor, used to make a copy of the object. Copy all of the
// fields of the 'existingInstance' to the new object. Reference types should
// be passed through a call to updateReference so that the depth of the copy
// can be controlled by the user. See the documentation of the ICloneWithContext
// interface for more information.
protected SquareRootScalar(SquareRootScalar existingInstance, CopyContext context) {
super(existingInstance, context);
m_scalar = context.updateReference(existingInstance.m_scalar);
}
// This is called to make a copy of the object, which it does by calling the
// copy constructor above.
@Override
public Object clone(CopyContext context) {
return new SquareRootScalar(this, context);
}
// This method is only called by the isSameDefinition method in the base class to
// determine if two scalars are equivalent. Derived classes MUST override this method and
// check all new fields introduced by the derived class for definitional equivalence. It
// is NOT necessary to check base class fields because the base class will already have
// done that.
@Override
protected final boolean checkForSameDefinition(Scalar other) {
SquareRootScalar o = (other instanceof SquareRootScalar) ? (SquareRootScalar) other : null;
return o != null &&
areSameDefinition(m_scalar, o.m_scalar);
}
// Called to determine a hash code for the current configuration of this object.
// Derived classes MUST override this method and compute a hash code that combines:
// a unique hash code seed, the base implementation result, and the
// hash codes of all new fields introduced by the derived class which are used
// in the CheckForSameDefinition method.
@Override
protected int computeCurrentDefinitionHashCode() {
return HashCode.combine(SquareRootScalar.class.hashCode(),
super.computeCurrentDefinitionHashCode(),
getDefinitionHashCode(m_scalar));
}
// Called to enumerate all of the other objects on which this object depends. This
// allows clients to navigate the graph of objects related to a computation.
@Override
public void enumerateDependencies(DependencyEnumerator enumerator) {
super.enumerateDependencies(enumerator);
enumerator.enumerate(m_scalar);
}
// The scalar that this scalar is the square root of.
public final Scalar getScalarToTakeSquareRootOf() {
return m_scalar;
}
public final void setScalarToTakeSquareRootOf(Scalar value) {
m_scalar = value;
}
// This method is responsible for returning an instance of the private
// Evaluator class. It should ensure that the properties are not null or
// in an invalid state, and then use the evaluator group when it constructs
// and returns an instance of the Evaluator.
@Override
public ScalarEvaluator getEvaluator(EvaluatorGroup group) {
if (group == null) {
throw new ArgumentNullException("group");
}
// Ensure that the properties are not null.
if (getScalarToTakeSquareRootOf() == null) {
throw new PropertyInvalidException("ScalarToTakeSquareRootOf", PropertyInvalidException.PropertyCannotBeNull);
}
return group.createEvaluator(getEvaluatorCallback);
}
private ScalarEvaluator createEvaluator(EvaluatorGroup group) {
// In order to take the square root of the scalar, we must first evaluate it.
// Get the evaluator that will allow us to do so.
// Notice that we create this evaluator in the same EvaluatorGroup.
ScalarEvaluator scalarEvaluator = getScalarToTakeSquareRootOf().getEvaluator(group);
return new Evaluator(group, scalarEvaluator);
}
private final EvaluatorGroup.Callback0<ScalarEvaluator> getEvaluatorCallback = EvaluatorGroup.Callback0.of(this::createEvaluator);
private Scalar m_scalar;
// This is the definition of the Evaluator that is used to actually evaluate this Scalar.
// Because it is a private, nested class, it is not visible outside of the SquareRootScalar class.
// This is ok, though, because once it is created users only interact with it via a reference
// to its base class: ScalarEvaluator.
private static final class Evaluator extends ScalarEvaluator {
// An evaluator should not store any data that the user will be able to change
// after creating the evaluator. This sometimes requires that data required by the
// evaluator be copied or frozen using the IFreezable interface.
public Evaluator(EvaluatorGroup group, ScalarEvaluator scalarEvaluator) {
super(group);
m_scalarEvaluator = scalarEvaluator;
}
// The Evaluator's copy constructor will be called from the Clone method.
// Don't forget to call the base class implementation!
private Evaluator(Evaluator existingInstance, CopyContext context) {
super(existingInstance, context);
// For non-evaluator reference types, we would use context.updateReference to
// allow the context to update the references we hold.
// This evaluator does not have any non-evaluator reference fields.
// For evaluators, just assign the reference directly - we'll call updateReference later.
m_scalarEvaluator = existingInstance.m_scalarEvaluator;
// Always call updateEvaluatorReferences at the end of the copy constructor.
// This is where references to evaluators will be updated.
updateEvaluatorReferences(context);
}
// This method is used by the EvaluatorGroup system to avoid redundant evaluations. The
// EvaluatorGroup may call it on your evaluator in order to replace your evaluator's
// reference to another evaluator with a reference to a version that caches its last
// result.
@Override
public void updateEvaluatorReferences(CopyContext context) {
m_scalarEvaluator = context.updateReference(m_scalarEvaluator);
}
// The clone method should call the copy constructor.
@Override
public Object clone(CopyContext context) {
return new Evaluator(this, context);
}
// This method determines if there is data available from this Evaluator at
// the specified date.
@Override
public boolean isAvailable(JulianDate date) {
// This evaluator is available whenever the nested evaluator is available.
return m_scalarEvaluator.isAvailable(date);
}
// This method returns a collection of time intervals when data is
// available from this Evaluator.
@Override
public TimeIntervalCollection getAvailabilityIntervals(TimeIntervalCollection consideredIntervals) {
// This evaluator is available whenever the nested evaluator is available.
return m_scalarEvaluator.getAvailabilityIntervals(consideredIntervals);
}
// This property determines if this Evaluator can safely be used from multiple threads
// simultaneously. If the evaluator stores data during the evaluate call, it is not thread
// safe. Otherwise, it generally is thread safe as long as any nested evaluators it uses
// are thread safe.
@Override
public boolean getIsThreadSafe() {
// This evaluator is thread safe as long as the nested evaluator is thread safe.
return m_scalarEvaluator.getIsThreadSafe();
}
// This property determines if this Evaluator result changes depending on the time at which it is evaluated.
@Override
public boolean getIsTimeVarying() {
return m_scalarEvaluator.getIsTimeVarying();
}
// This is where we do the actual evaluation when only the value of the scalar (not additional derivatives)
// is required.
@Override
public Double evaluate(JulianDate date) {
double value = m_scalarEvaluator.evaluate(date);
return Math.sqrt(value);
}
// This is where we do the actual evaluation when additional derivatives of the scalar
// are requested as well.
@Override
public Motion1<Double> evaluate(JulianDate date, int order) {
Motion1<Double> motion = m_scalarEvaluator.evaluate(date, order);
// Since only the second derivative is implemented here, constrain the array to
// only return up to that order.
int size = Math.min(motion.getOrder(), 2);
Double[] result = new Double[size + 1];
result[0] = Math.sqrt(motion.get(0));
// If the user did not request higher derivatives, do not spend time calculating them.
if (order > 0) {
// Compute the derivative using the chain rule.
result[1] = 0.5 * Math.pow(motion.get(0), -0.5) * motion.get(1);
}
if (order > 1) {
result[2] = 0.5 * Math.pow(motion.get(0), -0.5) * motion.get(2) - 0.25 * Math.pow(motion.get(0), -1.5) * motion.get(1) * motion.get(1);
}
return new Motion1<>(result);
}
// Override the dispose method to call the dispose() method on any nested
// evaluators or other disposable nested types.
@Override
protected void dispose(boolean disposing) {
if (disposing) {
m_scalarEvaluator.dispose();
}
}
private ScalarEvaluator m_scalarEvaluator;
}
}
Modifier | Constructor and Description |
---|---|
protected |
Scalar()
Initializes a new instance.
|
protected |
Scalar(Scalar existingInstance,
CopyContext context)
Initializes a new instance as a copy of an existing instance.
|
Modifier and Type | Method and Description |
---|---|
Scalar |
add(double scalar)
Adds a fixed scalar to this one.
|
static Scalar |
add(double left,
Scalar right)
Adds two scalars together.
|
Scalar |
add(Scalar scalar)
Adds another scalar to this one.
|
static Scalar |
add(Scalar left,
double right)
Adds two scalars together.
|
static Scalar |
add(Scalar left,
Scalar right)
Adds two scalars together.
|
protected boolean |
checkForSameDefinition(DefinitionalObject other)
Checks to determine if another instance has the same definition as this instance and
returns
true if it does. |
protected abstract boolean |
checkForSameDefinition(Scalar other)
Checks to determine if another instance has the same definition as this instance and
returns
true if it does. |
protected int |
computeCurrentDefinitionHashCode()
Computes a hash code based on the current properties of this object.
|
Scalar |
createScalarDerivative(int order)
Constructs a scalar which represents a derivative of this scalar.
|
Scalar |
divide(double scalar)
Divides this scalar (numerator) by a fixed value (denominator).
|
static Scalar |
divide(double left,
Scalar right)
Divides one scalar from another (left/right).
|
Scalar |
divide(Scalar scalar)
Divides this scalar (numerator) by another one (denominator).
|
static Scalar |
divide(Scalar left,
double right)
Divides one scalar from another (left/right).
|
static Scalar |
divide(Scalar left,
Scalar right)
Divides one scalar from another (left/right).
|
ScalarEvaluator |
getEvaluator()
Gets an evaluator that can be used to find the value of this scalar function at a given
JulianDate . |
abstract ScalarEvaluator |
getEvaluator(EvaluatorGroup group)
Gets an evaluator that can be used to find the value of this scalar function at a given
JulianDate . |
Scalar |
multiply(double scalar)
Multiplies this scalar with a fixed value.
|
static Scalar |
multiply(double left,
Scalar right)
Multiplies two scalars together.
|
Scalar |
multiply(Scalar scalar)
Multiplies another scalar with this one.
|
static Scalar |
multiply(Scalar left,
double right)
Multiplies two scalars together.
|
static Scalar |
multiply(Scalar left,
Scalar right)
Multiplies two scalars together.
|
Scalar |
power(double exponent)
Raises this scalar to the given fixed exponent.
|
Scalar |
subtract(double scalar)
Subtracts a fixed scalar from this one.
|
static Scalar |
subtract(double left,
Scalar right)
Subtracts one scalar from another.
|
Scalar |
subtract(Scalar scalar)
Subtracts another scalar from this one.
|
static Scalar |
subtract(Scalar left,
double right)
Subtracts one scalar from another.
|
static Scalar |
subtract(Scalar left,
Scalar right)
Subtracts one scalar from another.
|
static Scalar |
toScalar(double value)
Converts a constant double value to a
Scalar . |
areSameDefinition, areSameDefinition, areSameDefinition, areSameDefinition, areSameDefinition, clone, collectionItemsAreSameDefinition, collectionItemsAreSameDefinition, collectionItemsAreSameDefinition, dictionaryItemsAreSameDefinition, enumerateDependencies, freeze, freezeAggregatedObjects, getCollectionHashCode, getCollectionHashCode, getCollectionHashCode, getDefinitionHashCode, getDefinitionHashCode, getDefinitionHashCode, getDefinitionHashCode, getDefinitionHashCode, getDefinitionHashCode, getDictionaryHashCode, getIsFrozen, isSameDefinition, throwIfFrozen
protected Scalar()
protected Scalar(@Nonnull Scalar existingInstance, @Nonnull CopyContext context)
See ICloneWithContext.clone(CopyContext)
for more information about how to implement this constructor
in a derived class.
existingInstance
- The existing instance to copy.context
- A CopyContext
that controls the depth of the copy.ArgumentNullException
- Thrown when existingInstance
or context
is null
.protected final boolean checkForSameDefinition(DefinitionalObject other)
true
if it does. Derived classes MUST override this method and check
all new fields introduced by the derived class for definitional equivalence. It is NOT necessary
to check base class fields because the base class will already have done that. When overriding this method,
you should NOT call the base implementation because it will return false
for all derived-class instances.
Derived classes should check the type of other
to preserve the symmetric nature of IEquatableDefinition.isSameDefinition(java.lang.Object)
.checkForSameDefinition
in class DefinitionalObject
other
- The other instance to compare to this one.true
if the two objects are defined equivalently; otherwise false
.protected abstract boolean checkForSameDefinition(Scalar other)
true
if it does. Derived classes MUST override this method and check
all new fields introduced by the derived class for definitional equivalence. It is NOT necessary
to check base class fields because the base class will already have done that. When overriding this method,
you should NOT call the base implementation because it will return false
for all derived-class instances.
Derived classes should check the type of other
to preserve the symmetric nature of IEquatableDefinition.isSameDefinition(java.lang.Object)
.other
- The other instance to compare to this one.true
if the two objects are defined equivalently; otherwise false
.protected int computeCurrentDefinitionHashCode()
Scalar.checkForSameDefinition(agi.foundation.infrastructure.DefinitionalObject)
method.computeCurrentDefinitionHashCode
in class DefinitionalObject
@Nonnull public final ScalarEvaluator getEvaluator()
JulianDate
.@Nonnull public abstract ScalarEvaluator getEvaluator(@Nonnull EvaluatorGroup group)
JulianDate
.
Adds the evaluator to the EvaluatorGroup
.group
- The group with which to associate the new evaluator. By grouping evaluators
that are often evaluated at the same Julian dates, common computations can be performed only once
for the entire group instead of multiple times for each evaluator.@Nonnull public Scalar createScalarDerivative(int order)
order
- The order of derivative represented by the resultant scalar.ArgumentOutOfRangeException
- Thrown when order
is less than zero.@Nonnull public final Scalar add(@Nonnull Scalar scalar)
scalar
- The other scalar to add.ArgumentNullException
- Thrown when scalar
is null
.@Nonnull public final Scalar add(double scalar)
scalar
- The other scalar to add.@Nonnull public final Scalar subtract(@Nonnull Scalar scalar)
scalar
- The other scalar to subtract.ArgumentNullException
- Thrown when scalar
is null
.@Nonnull public final Scalar subtract(double scalar)
scalar
- The fixed scalar to subtract.@Nonnull public final Scalar multiply(@Nonnull Scalar scalar)
scalar
- The other scalar to multiply.ArgumentNullException
- Thrown when scalar
is null
.@Nonnull public final Scalar multiply(double scalar)
scalar
- The fixed value to multiply.@Nonnull public final Scalar divide(@Nonnull Scalar scalar)
scalar
- The other scalar to divide (denominator).ArgumentNullException
- Thrown when scalar
is null
.@Nonnull public final Scalar divide(double scalar)
scalar
- The fixed scalar to divide (denominator).public final Scalar power(double exponent)
exponent
- The exponent in the power term.public static Scalar add(Scalar left, Scalar right)
left
- The left hand scalar to add.right
- The right hand scalar to add.ArgumentNullException
- Thrown when left
or right
is null
.public static Scalar add(double left, Scalar right)
left
- The left hand scalar to add.right
- The right hand scalar to add.ArgumentNullException
- Thrown when right
is null
.public static Scalar add(Scalar left, double right)
left
- The left hand scalar to add.right
- The right hand scalar to add.ArgumentNullException
- Thrown when left
is null
.public static Scalar subtract(Scalar left, Scalar right)
left
- The left hand scalar from which to subtract.right
- The right hand scalar to subtract from the left.ArgumentNullException
- Thrown when left
or right
is null
.public static Scalar subtract(double left, Scalar right)
left
- The left hand scalar from which to subtract.right
- The right hand scalar to subtract from the left.ArgumentNullException
- Thrown when right
is null
.public static Scalar subtract(Scalar left, double right)
left
- The left hand scalar from which to subtract.right
- The right hand scalar to subtract from the left.ArgumentNullException
- Thrown when left
is null
.public static Scalar multiply(Scalar left, Scalar right)
left
- The first scalar term to multiply.right
- The second scalar term to multiply.ArgumentNullException
- Thrown when left
or right
is null
.public static Scalar multiply(double left, Scalar right)
left
- The first scalar term to multiply.right
- The second scalar term to multiply.ArgumentNullException
- Thrown when right
is null
.public static Scalar multiply(Scalar left, double right)
left
- The first scalar term to multiply.right
- The second scalar term to multiply.ArgumentNullException
- Thrown when left
is null
.public static Scalar divide(Scalar left, Scalar right)
left
- The numerator in the quotient.right
- The denominator in the quotient.ArgumentNullException
- Thrown when left
or right
is null
.public static Scalar divide(Scalar left, double right)
left
- The numerator in the quotient.right
- The denominator in the quotient.ArgumentNullException
- Thrown when left
is null
.public static Scalar divide(double left, Scalar right)
left
- The numerator in the quotient.right
- The denominator in the quotient.ArgumentNullException
- Thrown when right
is null
.