/******************************************************************************* * Copyright 2014 Analog Devices, Inc. * * Licensed 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 * * http://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 com.analog.lyric.dimple.parameters; import java.util.concurrent.atomic.AtomicIntegerArray; import net.jcip.annotations.ThreadSafe; import org.eclipse.jdt.annotation.Nullable; import com.google.common.util.concurrent.AtomicDoubleArray; @ThreadSafe public abstract class ParameterListN<Key extends IParameterKey> extends AbstractParameterList<Key> { private static final long serialVersionUID = 1L; protected final AtomicDoubleArray _values; protected final AtomicIntegerArray _fixedMask; /*-------------- * Construction */ protected ParameterListN(ParameterListN<Key> that) { AtomicDoubleArray thoseValues = that._values; int size = thoseValues.length(); _values = new AtomicDoubleArray(size); for (int i = 0; i < size; ++i) { _values.set(i, thoseValues.get(i)); } AtomicIntegerArray thatFixedMask = that._fixedMask; int fixedMaskSize = thatFixedMask.length(); _fixedMask = new AtomicIntegerArray(fixedMaskSize); for (int i = 0; i < fixedMaskSize; ++i) { _fixedMask.set(i, thatFixedMask.get(i)); } } protected ParameterListN(double ... values) { _values = new AtomicDoubleArray(values); int maskSize = maskSize(values.length); _fixedMask = new AtomicIntegerArray(maskSize); } protected ParameterListN(boolean fixed, double ... values) { this(values); if (fixed) { setAllFixed(fixed); } } protected ParameterListN(int size, double defaultValue) { _values = new AtomicDoubleArray(size); for (int i = 0; i < size; ++i) { _values.set(i, defaultValue); } _fixedMask = new AtomicIntegerArray(maskSize(size)); } protected ParameterListN(int size) { this(size, Double.NaN); } @Override public abstract ParameterListN<Key> clone(); /*------------------------------ * IFactorParameterList methods */ /** * {@inheritDoc} * <p> * This implementation does not support individual parameter sharing and will return false. */ @Override public boolean canShare() { return false; } @Override public final double get(int index) { return _values.get(index); } @Override public @Nullable SharedParameterValue getSharedValue(int index) { assertIndexInRange(index); return null; } @Override public final boolean isFixed(int index) { assertIndexInRange(index); int bit = 1 << (index & 31); int arrayIndex = index >>> 5; return (_fixedMask.get(arrayIndex) & bit) != 0; } @Override public boolean isShared(int index) { assertIndexInRange(index); return false; } @Override public void set(int index, double value) { assertNotFixed(index); _values.set(index, value); valueChanged(index); } @Override public final void setAllFixed(boolean fixed) { int mask = fixed ? -1 : 0; for (int i = 0, end = _fixedMask.length(); i < end; ++i) { _fixedMask.set(i, mask); } } @Override public final void setFixed(int index, boolean fixed) { final int bit = 1 << (index & 31); final int arrayIndex = index >>> 5; // Keep trying until bit is set correctly without changing any other bit. while (true) { int prevMask = _fixedMask.get(arrayIndex); int newMask = fixed ? prevMask|bit : prevMask&~bit; if (prevMask == newMask || _fixedMask.compareAndSet(arrayIndex, prevMask, newMask)) { break; } } } @Override public final void setShared(int index, boolean shared) { if (shared) { throw new UnsupportedOperationException( String.format("%s does no support shared parameter values.", getClass().getName())); } } @Override public final void setSharedValue(int index, @Nullable SharedParameterValue value) { setShared(index, value != null); } @Override public final int size() { return _values.length(); } /*----------------- * Private methods */ private static int maskSize(int size) { return (size + 31) / 32; } }