/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.mahout.math; /** * sparse matrix with general element values whose columns are accessible quickly. Implemented as a column array of * SparseVectors. */ public class SparseColumnMatrix extends AbstractMatrix { private Vector[] columnVectors; /** * Construct a matrix of the given cardinality with the given data columns * * @param rows * @param columns a RandomAccessSparseVector[] array of columns * @param columnVectors */ public SparseColumnMatrix(int rows, int columns, RandomAccessSparseVector[] columnVectors) { super(rows, columns); this.columnVectors = this.columnVectors.clone(); for (int col = 0; col < columnSize(); col++) { this.columnVectors[col] = this.columnVectors[col].clone(); } } /** * Construct a matrix of the given cardinality * * @param rows * @param columns */ public SparseColumnMatrix(int rows, int columns) { super(rows, columns); this.columnVectors = new RandomAccessSparseVector[columnSize()]; for (int col = 0; col < columnSize(); col++) { this.columnVectors[col] = new RandomAccessSparseVector(rowSize()); } } @Override public Matrix clone() { SparseColumnMatrix clone = (SparseColumnMatrix) super.clone(); clone.columnVectors = new Vector[columnVectors.length]; for (int i = 0; i < columnVectors.length; i++) { clone.columnVectors[i] = columnVectors[i].clone(); } return clone; } /** * Abstracted out for the iterator * @return {@link #numCols()} */ @Override public int numSlices() { return numCols(); } @Override public double getQuick(int row, int column) { return columnVectors[column] == null ? 0.0 : columnVectors[column].getQuick(row); } @Override public Matrix like() { return new SparseColumnMatrix(rowSize(), columnSize()); } @Override public Matrix like(int rows, int columns) { return new SparseColumnMatrix(rows, columns); } @Override public void setQuick(int row, int column, double value) { if (columnVectors[column] == null) { columnVectors[column] = new RandomAccessSparseVector(rowSize()); } columnVectors[column].setQuick(row, value); } @Override public int[] getNumNondefaultElements() { int[] result = new int[2]; result[COL] = columnVectors.length; for (int col = 0; col < columnSize(); col++) { result[ROW] = Math.max(result[ROW], columnVectors[col] .getNumNondefaultElements()); } return result; } @Override public Matrix viewPart(int[] offset, int[] size) { if (offset[ROW] < 0) { throw new IndexException(offset[ROW], columnVectors[COL].size()); } if (offset[ROW] + size[ROW] > columnVectors[COL].size()) { throw new IndexException(offset[ROW] + size[ROW], columnVectors[COL].size()); } if (offset[COL] < 0) { throw new IndexException(offset[COL], columnVectors.length); } if (offset[COL] + size[COL] > columnVectors.length) { throw new IndexException(offset[COL] + size[COL], columnVectors.length); } return new MatrixView(this, offset, size); } @Override public Matrix assignColumn(int column, Vector other) { if (rowSize() != other.size()) { throw new CardinalityException(rowSize(), other.size()); } if (column < 0 || column >= columnSize()) { throw new IndexException(column, columnSize()); } columnVectors[column].assign(other); return this; } @Override public Matrix assignRow(int row, Vector other) { if (columnSize() != other.size()) { throw new CardinalityException(columnSize(), other.size()); } if (row < 0 || row >= rowSize()) { throw new IndexException(row, rowSize()); } for (int col = 0; col < columnSize(); col++) { columnVectors[col].setQuick(row, other.getQuick(col)); } return this; } @Override public Vector viewColumn(int column) { if (column < 0 || column >= columnSize()) { throw new IndexException(column, columnSize()); } return columnVectors[column]; } }