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.util.concurrent.atomic.AtomicReference;
20
21 import org.hipparchus.Field;
22 import org.hipparchus.util.FastMath;
23
24 /** Field for {@link Gradient} instances.
25 * @since 1.7
26 */
27 public class GradientField implements Field<Gradient> {
28
29 /** Array of all fields created so far. */
30 private static AtomicReference<GradientField[]> fields = new AtomicReference<>(null);
31
32 /** Zero constant. */
33 private final Gradient zero;
34
35 /** One constant. */
36 private final Gradient one;
37
38 /** Associated factory for conversions to {@link DerivativeStructure}. */
39 private final DSFactory factory;
40
41 /** Private constructor.
42 * @param parameters number of free parameters
43 */
44 private GradientField(final int parameters) {
45 zero = new Gradient(0.0, new double[parameters]);
46 one = new Gradient(1.0, new double[parameters]);
47 factory = new DSFactory(parameters, 1);
48 }
49
50 /** Get the field for number of free parameters.
51 * @param parameters number of free parameters
52 * @return cached field
53 */
54 public static GradientField getField(int parameters) {
55
56 // get the cached fields
57 final GradientField[] cache = fields.get();
58 if (cache != null && cache.length > parameters && cache[parameters] != null) {
59 // the field has already been created
60 return cache[parameters];
61 }
62
63 // we need to create a new field
64 final int maxParameters = FastMath.max(parameters, cache == null ? 0 : cache.length);
65 final GradientField[] newCache = new GradientField[maxParameters + 1];
66
67 if (cache != null) {
68 // preserve the already created fields
69 System.arraycopy(cache, 0, newCache, 0, cache.length);
70 }
71
72 // create the new field
73 newCache[parameters] = new GradientField(parameters);
74
75 // atomically reset the cached fileds array
76 fields.compareAndSet(cache, newCache);
77
78 return newCache[parameters];
79
80 }
81
82 /** {@inheritDoc} */
83 @Override
84 public Gradient getOne() {
85 return one;
86 }
87
88 /** {@inheritDoc} */
89 @Override
90 public Gradient getZero() {
91 return zero;
92 }
93
94 /** {@inheritDoc} */
95 @Override
96 public Class<Gradient> getRuntimeClass() {
97 return Gradient.class;
98 }
99
100 /** Get the factory for converting to {@link DerivativeStructure}.
101 * <p>
102 * This factory is used only for conversions. {@code Gradient} by
103 * itself does not rely at all on {@link DSFactory}, {@link DSCompiler}
104 * or {@link DerivativeStructure} for its computation. For this reason,
105 * the factory here is hidden and this method is package private, so
106 * only {@link Gradient#toDerivativeStructure()} can call it on an
107 * existing {@link Gradient} instance
108 * </p>
109 * @return factory for conversions
110 */
111 DSFactory getConversionFactory() {
112 return factory;
113 }
114
115 /** {@inheritDoc} */
116 @Override
117 public boolean equals(final Object other) {
118 return this == other;
119 }
120
121 /** {@inheritDoc} */
122 @Override
123 public int hashCode() {
124 return 0x26ca1af0;
125 }
126
127 }