/* * Copyright (C) 2008-2015 by Holger Arndt * * This file is part of the Universal Java Matrix Package (UJMP). * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * UJMP is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * UJMP is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with UJMP; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package org.ujmp.core.objectmatrix.calculation; import java.util.Collection; import java.util.TreeMap; import org.ujmp.core.Coordinates; import org.ujmp.core.Matrix; import org.ujmp.core.enums.ValueType; import org.ujmp.core.mapmatrix.DefaultMapMatrix; import org.ujmp.core.mapmatrix.MapMatrix; import org.ujmp.core.objectmatrix.impl.DefaultSparseObjectMatrix; import org.ujmp.core.util.VerifyUtil; // TODO: should work in more than 2 dimensions public class Concatenation extends AbstractObjectCalculation { private static final long serialVersionUID = -2428322597419645314L; private long[] positions = null; private long[] size = Coordinates.ZERO2D; private ValueType valueType = null; public Concatenation(int dimension, Matrix... matrices) { super(dimension, matrices); for (int i = 0; i < matrices.length - 1; i++) { Matrix m0 = matrices[i]; Matrix m1 = matrices[i + 1]; VerifyUtil.verifyNotNull(m0, "matrix is null"); VerifyUtil.verifyNotNull(m1, "matrix is null"); VerifyUtil.verifyEquals(m0.getDimensionCount(), m1.getDimensionCount(), "matrices have different dimensionality"); } if (dimension > matrices[0].getDimensionCount() + 1) { throw new IllegalArgumentException("too many dimensions"); } // extends dimensionality if necessary if (dimension > matrices[0].getDimensionCount()) { long[] oldSize = matrices[0].getSize(); long[] newSize = new long[oldSize.length + 1]; System.arraycopy(oldSize, 0, newSize, 0, oldSize.length); newSize[newSize.length - 1] = 1; for (int i = 0; i < matrices.length; i++) { matrices[i] = matrices[i].reshape(Ret.LINK, newSize); } } for (int i = 0; i < matrices.length - 1; i++) { Matrix m0 = matrices[i]; Matrix m1 = matrices[i + 1]; long[] s0 = m0.getSize(); long[] s1 = Coordinates.copyOf(m1.getSize()); if (!Coordinates.allEquals(s0, 0) && !Coordinates.allEquals(s1, 0)) { s1[dimension] = s0[dimension]; VerifyUtil.verifyEquals(s0, s1, "matrices have different sizes"); } } valueType = matrices[0].getValueType(); positions = new long[matrices.length]; long pos = 0; for (int i = 0; i < matrices.length; i++) { Matrix m = matrices[i]; if (!valueType.equals(m.getValueType())) { valueType = ValueType.OBJECT; } positions[i] = pos; pos += m.getSize(dimension); size = Coordinates.max(size, m.getSize()); } size[dimension] = pos; // set total size // Annotation if (matrices[0].getLabelObject() != null) { MapMatrix<String, Object> annotation = new DefaultMapMatrix<String, Object>( new TreeMap<String, Object>()); setMetaData(annotation); annotation.put(Matrix.LABEL, matrices[0].getLabelObject()); for (int d = 0; d < matrices[0].getDimensionCount(); d++) { if (d == dimension) { annotation.put(Matrix.DIMENSIONMETADATA + d, matrices[0].getMetaDataDimensionMatrix(d)); } else { Matrix[] annotationMatrices = new Matrix[matrices.length]; for (int i = 0; i < annotationMatrices.length; i++) { MapMatrix<String, Object> a = matrices[i].getMetaData(); Matrix am = null; if (a == null) { long[] size = Coordinates.copyOf(matrices[i].getSize()); size[d] = 1; am = new DefaultSparseObjectMatrix(size); } else { am = (Matrix) a.get(Matrix.DIMENSIONMETADATA + d); if (am == null) { long[] size = Coordinates.copyOf(matrices[i].getSize()); size[d] = 1; am = new DefaultSparseObjectMatrix(size); } } annotationMatrices[i] = am; } Matrix m = new Concatenation(dimension, annotationMatrices).calc(Ret.NEW); annotation.put(Matrix.DIMENSIONMETADATA + d, m); } } } } public Concatenation(int dimension, Collection<Matrix> matrices) { this(dimension, matrices.toArray(new Matrix[matrices.size()])); } public Object getObject(long... coordinates) { int i = 0; for (; i < positions.length; i++) { if (positions[i] > coordinates[getDimension()]) { break; } } i--; Matrix m = getSources()[i]; long[] c = Coordinates.copyOf(coordinates); c[getDimension()] = c[getDimension()] - positions[i]; return m.getAsObject(c); } public long[] getSize() { return size; } public void setObject(Object value, long... coordinates) { } public final ValueType getValueType() { return valueType; } }