FDSFactory.java
- /*
- * Licensed to the Hipparchus project under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.hipparchus.analysis.differentiation;
- import org.hipparchus.CalculusFieldElement;
- import org.hipparchus.Field;
- import org.hipparchus.exception.LocalizedCoreFormats;
- import org.hipparchus.exception.MathIllegalArgumentException;
- import org.hipparchus.util.MathArrays;
- /** Factory for {@link FieldDerivativeStructure}.
- * <p>This class is a factory for {@link FieldDerivativeStructure} instances.</p>
- * <p>Instances of this class are guaranteed to be immutable.</p>
- * @see FieldDerivativeStructure
- * @param <T> the type of the function parameters and value
- */
- public class FDSFactory<T extends CalculusFieldElement<T>> {
- /** Compiler for the current dimensions. */
- private final DSCompiler compiler;
- /** Field the value and parameters of the function belongs to. */
- private final Field<T> valueField;
- /** Field the {@link FieldDerivativeStructure} instances belong to. */
- private final DerivativeField<T> derivativeField;
- /** Simple constructor.
- * @param valueField field for the function parameters and value
- * @param parameters number of free parameters
- * @param order derivation order
- */
- public FDSFactory(final Field<T> valueField, final int parameters, final int order) {
- this.compiler = DSCompiler.getCompiler(parameters, order);
- this.valueField = valueField;
- this.derivativeField = new DerivativeField<>(constant(valueField.getZero()),
- constant(valueField.getOne()),
- constant(valueField.getZero().getPi()));
- }
- /** Get the {@link Field} the value and parameters of the function belongs to.
- * @return {@link Field} the value and parameters of the function belongs to
- */
- public Field<T> getValueField() {
- return valueField;
- }
- /** Get the {@link Field} the {@link FieldDerivativeStructure} instances belong to.
- * @return {@link Field} the {@link FieldDerivativeStructure} instances belong to
- */
- public DerivativeField<T> getDerivativeField() {
- return derivativeField;
- }
- /** Build a {@link FieldDerivativeStructure} representing a constant value.
- * @param value value of the constant
- * @return a {@link FieldDerivativeStructure} representing a constant value
- */
- public FieldDerivativeStructure<T> constant(double value) {
- return constant(valueField.getZero().add(value));
- }
- /** Build a {@link FieldDerivativeStructure} representing a constant value.
- * @param value value of the constant
- * @return a {@link FieldDerivativeStructure} representing a constant value
- */
- public FieldDerivativeStructure<T> constant(final T value) {
- final FieldDerivativeStructure<T> fds = new FieldDerivativeStructure<>(this);
- fds.setDerivativeComponent(0, value);
- return fds;
- }
- /** Build a {@link FieldDerivativeStructure} representing a variable.
- * <p>Instances built using this method are considered
- * to be the free variables with respect to which differentials
- * are computed. As such, their differential with respect to
- * themselves is +1.</p>
- * @param index index of the variable (from 0 to
- * {@link #getCompiler()}.{@link DSCompiler#getFreeParameters() getFreeParameters()} - 1)
- * @param value value of the variable
- * @return a {@link FieldDerivativeStructure} representing a variable
- * @exception MathIllegalArgumentException if index if greater or
- * equal to {@link #getCompiler()}.{@link DSCompiler#getFreeParameters() getFreeParameters()}.
- */
- public FieldDerivativeStructure<T> variable(final int index, final T value)
- throws MathIllegalArgumentException {
- if (index >= getCompiler().getFreeParameters()) {
- throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE_BOUND_EXCLUDED,
- index, getCompiler().getFreeParameters());
- }
- final FieldDerivativeStructure<T> fds = new FieldDerivativeStructure<>(this);
- fds.setDerivativeComponent(0, value);
- if (getCompiler().getOrder() > 0) {
- // the derivative of the variable with respect to itself is 1.
- fds.setDerivativeComponent(DSCompiler.getCompiler(index, getCompiler().getOrder()).getSize(),
- valueField.getOne());
- }
- return fds;
- }
- /** Build a {@link FieldDerivativeStructure} representing a variable.
- * <p>Instances built using this method are considered
- * to be the free variables with respect to which differentials
- * are computed. As such, their differential with respect to
- * themselves is +1.</p>
- * @param index index of the variable (from 0 to
- * {@link #getCompiler()}.{@link DSCompiler#getFreeParameters() getFreeParameters()} - 1)
- * @param value value of the variable
- * @return a {@link FieldDerivativeStructure} representing a variable
- * @exception MathIllegalArgumentException if index if greater or
- * equal to {@link #getCompiler()}.{@link DSCompiler#getFreeParameters() getFreeParameters()}.
- */
- public FieldDerivativeStructure<T> variable(final int index, final double value)
- throws MathIllegalArgumentException {
- if (index >= getCompiler().getFreeParameters()) {
- throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE_BOUND_EXCLUDED,
- index, getCompiler().getFreeParameters());
- }
- final FieldDerivativeStructure<T> fds = new FieldDerivativeStructure<>(this);
- fds.setDerivativeComponent(0, valueField.getZero().newInstance(value));
- if (getCompiler().getOrder() > 0) {
- // the derivative of the variable with respect to itself is 1.
- fds.setDerivativeComponent(DSCompiler.getCompiler(index, getCompiler().getOrder()).getSize(),
- valueField.getOne());
- }
- return fds;
- }
- /** Build a {@link FieldDerivativeStructure} from all its derivatives.
- * @param derivatives derivatives sorted according to
- * {@link DSCompiler#getPartialDerivativeIndex(int...)}
- * @return {@link FieldDerivativeStructure} with specified derivatives
- * @exception MathIllegalArgumentException if derivatives array does not match the
- * {@link DSCompiler#getSize() size} expected by the compiler
- * @exception MathIllegalArgumentException if order is too large
- * @see FieldDerivativeStructure#getAllDerivatives()
- */
- @SafeVarargs
- public final FieldDerivativeStructure<T> build(final T ... derivatives)
- throws MathIllegalArgumentException {
- final T[] data = buildArray();
- if (derivatives.length != data.length) {
- throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
- derivatives.length, data.length);
- }
- System.arraycopy(derivatives, 0, data, 0, data.length);
- return new FieldDerivativeStructure<>(this, data);
- }
- /** Build a {@link FieldDerivativeStructure} from all its derivatives.
- * @param derivatives derivatives sorted according to
- * {@link DSCompiler#getPartialDerivativeIndex(int...)}
- * @return {@link FieldDerivativeStructure} with specified derivatives
- * @exception MathIllegalArgumentException if derivatives array does not match the
- * {@link DSCompiler#getSize() size} expected by the compiler
- * @exception MathIllegalArgumentException if order is too large
- * @see FieldDerivativeStructure#getAllDerivatives()
- */
- public FieldDerivativeStructure<T> build(final double ... derivatives)
- throws MathIllegalArgumentException {
- final T[] data = buildArray();
- if (derivatives.length != data.length) {
- throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
- derivatives.length, data.length);
- }
- for (int i = 0; i < data.length; ++i) {
- data[i] = valueField.getZero().add(derivatives[i]);
- }
- return new FieldDerivativeStructure<>(this, data);
- }
- /** Build a {@link FieldDerivativeStructure} with an uninitialized array.
- * <p>This method is intended only for FieldDerivativeStructure internal use.</p>
- * @return a {@link FieldDerivativeStructure} with an uninitialized array
- */
- FieldDerivativeStructure<T> build() {
- return new FieldDerivativeStructure<>(this);
- }
- /** Build an uninitialized array for derivatives data.
- * @return uninitialized array for derivatives data
- */
- private T[] buildArray() {
- return MathArrays.buildArray(valueField, compiler.getSize());
- }
- /** Get the compiler for the current dimensions.
- * @return compiler for the current dimensions
- */
- public DSCompiler getCompiler() {
- return compiler;
- }
- /** Check rules set compatibility.
- * @param factory other factory field to check against instance
- * @exception MathIllegalArgumentException if number of free parameters or orders are inconsistent
- */
- void checkCompatibility(final FDSFactory<T> factory) throws MathIllegalArgumentException {
- compiler.checkCompatibility(factory.compiler);
- }
- /** Field for {link FieldDerivativeStructure} instances.
- * @param <T> the type of the function parameters and value
- */
- public static class DerivativeField<T extends CalculusFieldElement<T>> implements Field<FieldDerivativeStructure<T>> {
- /** Constant function evaluating to 0.0. */
- private final FieldDerivativeStructure<T> zero;
- /** Constant function evaluating to 1.0. */
- private final FieldDerivativeStructure<T> one;
- /** Constant function evaluating to π. */
- private final FieldDerivativeStructure<T> pi;
- /** Simple constructor.
- * @param zero constant function evaluating to 0.0
- * @param one constant function evaluating to 1.0
- * @param pi constant function evaluating to π
- */
- DerivativeField(final FieldDerivativeStructure<T> zero,
- final FieldDerivativeStructure<T> one,
- final FieldDerivativeStructure<T> pi) {
- this.zero = zero;
- this.one = one;
- this.pi = pi;
- }
- /** {@inheritDoc} */
- @Override
- public FieldDerivativeStructure<T> getZero() {
- return zero;
- }
- /** {@inheritDoc} */
- @Override
- public FieldDerivativeStructure<T> getOne() {
- return one;
- }
- /** Get the Archimedes constant π.
- * <p>
- * Archimedes constant is the ratio of a circle's circumference to its diameter.
- * </p>
- * @return Archimedes constant π
- * @since 2.0
- */
- public FieldDerivativeStructure<T> getPi() {
- return pi;
- }
- /** {@inheritDoc} */
- @SuppressWarnings("unchecked")
- @Override
- public Class<FieldDerivativeStructure<T>> getRuntimeClass() {
- return (Class<FieldDerivativeStructure<T>>) zero.getClass();
- }
- /** {@inheritDoc} */
- @Override
- public boolean equals(final Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof DerivativeField) {
- FDSFactory<T> lhsFactory = zero.getFactory();
- FDSFactory<?> rhsFactory = ((DerivativeField<?>) other).zero.getFactory();
- return lhsFactory.compiler == rhsFactory.compiler &&
- lhsFactory.valueField.equals(rhsFactory.valueField);
- } else {
- return false;
- }
- }
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- final DSCompiler compiler = zero.getFactory().getCompiler();
- return 0x58d35de8 ^ (compiler.getFreeParameters() << 16 & compiler.getOrder());
- }
- }
- }