/******************************************************************************* * 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.benchmarking.utils.doublespace; import java.util.AbstractCollection; import java.util.AbstractSet; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Set; import org.eclipse.jdt.annotation.NonNull; import com.analog.lyric.benchmarking.utils.functional.BinaryOp; import com.analog.lyric.benchmarking.utils.functional.FoldFunction; import com.analog.lyric.benchmarking.utils.functional.Functions; import com.analog.lyric.benchmarking.utils.functional.IterFunctionWithCoordinates; import com.analog.lyric.benchmarking.utils.functional.TransformFunction; /** * Provides a skeletal implementation of the DoubleSpace interface. */ public abstract class AbstractDoubleSpace implements DoubleSpace { private final Set<Entry> _entrySet = Collections.unmodifiableSet(new AbstractSet<Entry>() { @Override public Iterator<Entry> iterator() { return new EntryIterator(); } @Override public int size() { return getCardinality(); } }); protected final JointIndexer _jointIndexer; private final Collection<Double> _valuesCollection = Collections.unmodifiableCollection(new AbstractCollection<Double>() { @Override public Iterator<Double> iterator() { return new ValueIterator(); } @Override public int size() { return getCardinality(); } }); /** * Constructor that must be invoked by derived classes. * * @param indexer * The provided joint indexer describes the domain of the space. */ protected AbstractDoubleSpace(final JointIndexer indexer) { _jointIndexer = indexer; } @Override public DoubleSpace add(DoubleSpace rhs) { return binaryOp(rhs, Functions.add); } @Override public DoubleSpace binaryOp(DoubleSpace rhs, BinaryOp op) { final int dimensions = getDimensionsCount(); if (dimensions != rhs.getDimensionsCount()) { throw new IllegalArgumentException("dimensions must match."); } for (int dimension = 0; dimension < dimensions; dimension++) { if (getIndexer(dimension).getCardinality() != rhs.getIndexer(dimension).getCardinality()) { throw new IllegalArgumentException("dimensions must match."); } } final Iterator<int[]> it_coords_this = coordinatesSet().iterator(); final Iterator<int[]> it_coords_that = rhs.coordinatesSet().iterator(); while (it_coords_this.hasNext() && it_coords_that.hasNext()) { final int[] coords_this = it_coords_this.next(); final int[] coords_that = it_coords_that.next(); put(op.apply(get(coords_this), rhs.get(coords_that)), coords_this); } return this; } @Override public Set<int[]> coordinatesSet() { return _jointIndexer.coordinatesSet(); } @Override public Set<Entry> entrySet() { return _entrySet; } @NonNull // FIXME - workaround for Eclipse JDT bug (467610?) @Override public <T> T fold(T init, FoldFunction<T> fn) { T acc = init; for (final int[] coordinates : coordinatesSet()) { final double value = get(coordinates); acc = fn.apply(acc, value); } return acc; } @Override public int[] getDimensions() { final int[] orders = new int[getDimensionsCount()]; for (int dimension = 0; dimension < orders.length; dimension++) { orders[dimension] = getIndexer(dimension).getCardinality(); } return orders; } @Override public int getDimensionsCount() { return _jointIndexer.getDimensionsCount(); } @Override public Indexer getIndexer(int dimension) { return _jointIndexer.getIndexer(dimension); } @Override public void iter(IterFunctionWithCoordinates fn) { for (final int[] coordinates : coordinatesSet()) { final double value = get(coordinates); fn.apply(value, coordinates); } } @Override public DoubleSpace transform(TransformFunction transformer) { for (final int[] coords : coordinatesSet()) { put(transformer.apply(get(coords)), coords); } return this; } @Override public Collection<Double> values() { return _valuesCollection; } @Override public DoubleSpace view(Indexer... indexers) { return new IndexedDoubleSpace(this, indexers); } private final class EntryIterator implements Iterator<Entry> { private final Iterator<int[]> _coordinatesIterator; public EntryIterator() { _coordinatesIterator = coordinatesSet().iterator(); } @Override public boolean hasNext() { return _coordinatesIterator.hasNext(); } @Override public Entry next() { final int[] coordinates = _coordinatesIterator.next(); return new Entry(AbstractDoubleSpace.this, coordinates); } @Override public void remove() { throw new UnsupportedOperationException(); } } private final class ValueIterator implements Iterator<Double> { private final Iterator<int[]> _coordinatesIterator; public ValueIterator() { _coordinatesIterator = coordinatesSet().iterator(); } @Override public boolean hasNext() { return _coordinatesIterator.hasNext(); } @Override public Double next() { final int[] coordinates = _coordinatesIterator.next(); final double value = get(coordinates); return value; } @Override public void remove() { throw new UnsupportedOperationException(); } } }