001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.math3.linear;
018    
019    import org.apache.commons.math3.Field;
020    import org.apache.commons.math3.FieldElement;
021    import org.apache.commons.math3.util.OpenIntToFieldHashMap;
022    
023    /**
024     * Sparse matrix implementation based on an open addressed map.
025     *
026     * @param <T> the type of the field elements
027     * @version $Id: SparseFieldMatrix.java 1416643 2012-12-03 19:37:14Z tn $
028     * @since 2.0
029     * @deprecated As of version 3.1, this class is deprecated, for reasons exposed
030     * in this JIRA
031     * <a href="https://issues.apache.org/jira/browse/MATH-870">ticket</a>. This
032     * class will be removed in version 4.0.
033     *
034     */
035    @Deprecated
036    public class SparseFieldMatrix<T extends FieldElement<T>> extends AbstractFieldMatrix<T> {
037    
038        /** Storage for (sparse) matrix elements. */
039        private final OpenIntToFieldHashMap<T> entries;
040        /** Row dimension. */
041        private final int rows;
042        /** Column dimension. */
043        private final int columns;
044    
045        /**
046         * Create a matrix with no data.
047         *
048         * @param field Field to which the elements belong.
049         */
050        public SparseFieldMatrix(final Field<T> field) {
051            super(field);
052            rows = 0;
053            columns= 0;
054            entries = new OpenIntToFieldHashMap<T>(field);
055        }
056    
057        /**
058         * Create a new SparseFieldMatrix<T> with the supplied row and column
059         * dimensions.
060         *
061         * @param field Field to which the elements belong.
062         * @param rowDimension Number of rows in the new matrix.
063         * @param columnDimension Number of columns in the new matrix.
064         * @throws org.apache.commons.math3.exception.NotStrictlyPositiveException
065         * if row or column dimension is not positive.
066         */
067        public SparseFieldMatrix(final Field<T> field,
068                                 final int rowDimension, final int columnDimension) {
069            super(field, rowDimension, columnDimension);
070            this.rows = rowDimension;
071            this.columns = columnDimension;
072            entries = new OpenIntToFieldHashMap<T>(field);
073        }
074    
075        /**
076         * Copy constructor.
077         *
078         * @param other Instance to copy.
079         */
080        public SparseFieldMatrix(SparseFieldMatrix<T> other) {
081            super(other.getField(), other.getRowDimension(), other.getColumnDimension());
082            rows = other.getRowDimension();
083            columns = other.getColumnDimension();
084            entries = new OpenIntToFieldHashMap<T>(other.entries);
085        }
086    
087        /**
088         * Generic copy constructor.
089         *
090         * @param other Instance to copy.
091         */
092        public SparseFieldMatrix(FieldMatrix<T> other){
093            super(other.getField(), other.getRowDimension(), other.getColumnDimension());
094            rows = other.getRowDimension();
095            columns = other.getColumnDimension();
096            entries = new OpenIntToFieldHashMap<T>(getField());
097            for (int i = 0; i < rows; i++) {
098                for (int j = 0; j < columns; j++) {
099                    setEntry(i, j, other.getEntry(i, j));
100                }
101            }
102        }
103    
104        /** {@inheritDoc} */
105        @Override
106        public void addToEntry(int row, int column, T increment) {
107            checkRowIndex(row);
108            checkColumnIndex(column);
109            final int key = computeKey(row, column);
110            final T value = entries.get(key).add(increment);
111            if (getField().getZero().equals(value)) {
112                entries.remove(key);
113            } else {
114                entries.put(key, value);
115            }
116        }
117    
118        /** {@inheritDoc} */
119        @Override
120        public FieldMatrix<T> copy() {
121            return new SparseFieldMatrix<T>(this);
122        }
123    
124        /** {@inheritDoc} */
125        @Override
126        public FieldMatrix<T> createMatrix(int rowDimension, int columnDimension) {
127            return new SparseFieldMatrix<T>(getField(), rowDimension, columnDimension);
128        }
129    
130        /** {@inheritDoc} */
131        @Override
132        public int getColumnDimension() {
133            return columns;
134        }
135    
136        /** {@inheritDoc} */
137        @Override
138        public T getEntry(int row, int column) {
139            checkRowIndex(row);
140            checkColumnIndex(column);
141            return entries.get(computeKey(row, column));
142        }
143    
144        /** {@inheritDoc} */
145        @Override
146        public int getRowDimension() {
147            return rows;
148        }
149    
150        /** {@inheritDoc} */
151        @Override
152        public void multiplyEntry(int row, int column, T factor) {
153            checkRowIndex(row);
154            checkColumnIndex(column);
155            final int key = computeKey(row, column);
156            final T value = entries.get(key).multiply(factor);
157            if (getField().getZero().equals(value)) {
158                entries.remove(key);
159            } else {
160                entries.put(key, value);
161            }
162    
163        }
164    
165        /** {@inheritDoc} */
166        @Override
167        public void setEntry(int row, int column, T value) {
168            checkRowIndex(row);
169            checkColumnIndex(column);
170            if (getField().getZero().equals(value)) {
171                entries.remove(computeKey(row, column));
172            } else {
173                entries.put(computeKey(row, column), value);
174            }
175        }
176    
177        /**
178         * Compute the key to access a matrix element.
179         *
180         * @param row Row index of the matrix element.
181         * @param column Column index of the matrix element.
182         * @return the key within the map to access the matrix element.
183         */
184        private int computeKey(int row, int column) {
185            return row * columns + column;
186        }
187    }