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 }