1 /*
2 * Licensed to the Hipparchus project under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.hipparchus.analysis.differentiation;
18
19 import java.lang.reflect.Array;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import org.hipparchus.CalculusFieldElement;
24 import org.hipparchus.Field;
25 import org.hipparchus.util.MathArrays;
26
27 /** Field for {@link Gradient} instances.
28 * @param <T> the type of the function parameters and value
29 * @since 1.7
30 */
31 public class FieldGradientField<T extends CalculusFieldElement<T>> implements Field<FieldGradient<T>> {
32
33 /** Cached fields. */
34 private static final Map<Field<?>, FieldGradientField<?>[]> CACHE = new HashMap<>();
35
36 /** Zero constant. */
37 private final FieldGradient<T> zero;
38
39 /** One constant. */
40 private final FieldGradient<T> one;
41
42 /** Associated factory for conversions to {@link DerivativeStructure}. */
43 private final FDSFactory<T> factory;
44
45 /** Private constructor.
46 * @param valueField field for the function parameters and value
47 * @param parameters number of free parameters
48 */
49 private FieldGradientField(final Field<T> valueField, final int parameters) {
50 zero = new FieldGradient<>(valueField.getZero(), MathArrays.buildArray(valueField, parameters));
51 one = new FieldGradient<>(valueField.getOne(), MathArrays.buildArray(valueField, parameters));
52 factory = new FDSFactory<>(valueField, parameters, 1);
53 }
54
55 /** Get the field for number of free parameters.
56 * @param valueField field for the function parameters and value
57 * @param parameters number of free parameters
58 * @param <T> the type of the function parameters and value
59 * @return cached field
60 */
61 public static <T extends CalculusFieldElement<T>> FieldGradientField<T> getField(final Field<T> valueField, final int parameters) {
62
63 FieldGradientField<?>[] cachedFields;
64 synchronized (CACHE) {
65 cachedFields = CACHE.get(valueField);
66 if (cachedFields == null || cachedFields.length <= parameters) {
67 FieldGradientField<?>[] newCachedFields =
68 (FieldGradientField<?>[]) Array.newInstance(FieldGradientField.class, parameters + 1);
69 if (cachedFields != null) {
70 // preserve the already created fields
71 System.arraycopy(cachedFields, 0, newCachedFields, 0, cachedFields.length);
72 }
73 cachedFields = newCachedFields;
74 CACHE.put(valueField, cachedFields);
75 }
76 }
77
78 if (cachedFields[parameters] == null) {
79 // we need to create a new field
80 cachedFields[parameters] = new FieldGradientField<>(valueField, parameters);
81 }
82
83 @SuppressWarnings("unchecked")
84 final FieldGradientField<T> tCached = (FieldGradientField<T>) cachedFields[parameters];
85 return tCached;
86
87 }
88
89 /** {@inheritDoc} */
90 @Override
91 public FieldGradient<T> getOne() {
92 return one;
93 }
94
95 /** {@inheritDoc} */
96 @Override
97 public FieldGradient<T> getZero() {
98 return zero;
99 }
100
101 /** {@inheritDoc} */
102 @SuppressWarnings("unchecked")
103 @Override
104 public Class<FieldGradient<T>> getRuntimeClass() {
105 return (Class<FieldGradient<T>>) getZero().getClass();
106 }
107
108 /** Get the factory for converting to {@link DerivativeStructure}.
109 * <p>
110 * This factory is used only for conversions. {@code Gradient} by
111 * itself does not rely at all on {@link DSFactory}, {@link DSCompiler}
112 * or {@link DerivativeStructure} for its computation. For this reason,
113 * the factory here is hidden and this method is package private, so
114 * only {@link Gradient#toDerivativeStructure()} can call it on an
115 * existing {@link Gradient} instance
116 * </p>
117 * @return factory for conversions
118 */
119 FDSFactory<T> getConversionFactory() {
120 return factory;
121 }
122
123 /** {@inheritDoc} */
124 @Override
125 public boolean equals(final Object other) {
126 return this == other;
127 }
128
129 /** {@inheritDoc} */
130 @Override
131 public int hashCode() {
132 return 0xcd3e92ee;
133 }
134
135 }