/*
 Copyright (C) 2007 Richard Gomes

 This file is part of JQuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://jquantlib.org/

 JQuantLib is free software: you can redistribute it and/or modify it
 under the terms of the QuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 . The license is also available online at
 .

 This program 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 license for more details.

 JQuantLib is based on QuantLib. http://quantlib.org/
 When applicable, the original copyright notice follows this notice.
 */

package org.jquantlib.math.matrixutilities;

import java.util.Set;

import org.jquantlib.QL;
import org.jquantlib.lang.exceptions.LibraryException;
import org.jquantlib.math.matrixutilities.internal.Address;

/**
 * This class provides efficient basement for matrix operations by mapping matrices onto
 * a linear array, which performs better than bidimensional arrays.
 * 

* In addition, access to elements is calculated by a certain policy which is intended to * Matrix elements need to be translated to the underlying linear * storage when they are read or written. * * @author Richard Gomes */ public abstract class Cells implements Cloneable { // // private final static fields :: error messages // private final static String FORTRAN_ADDRESSING_EXPECTED = "variable \"%s\" should be FORTRAN-style addressing"; // // protected final static fields :: error messages // protected final static String INVALID_ARGUMENTS = "invalid arguments"; protected final static String WRONG_BUFFER_LENGTH = "wrong buffer length"; protected final static String MATRIX_IS_INCOMPATIBLE = "matrix is incompatible"; protected final static String ARRAY_IS_INCOMPATIBLE = "array is incompatible"; protected final static String ITERATOR_IS_INCOMPATIBLE = "iterator is incompatible"; protected final static String NOT_ENOUGH_STORAGE = "not enough storage area for operation"; protected final static String MATRIX_MUST_BE_SQUARE = "matrix must be square"; protected final static String MATRIX_MUST_BE_SYMMETRIC = "matrix must be symmetric"; protected final static String MATRIX_IS_SINGULAR = "matrix is singular"; protected final static String NON_CONTIGUOUS_DATA = "Operation not supported on non-contiguous data"; // // protected fields // protected final int rows; protected final int cols; protected final int size; // // protected fields // protected T addr; // // public fields // /** * This is the internal data storage where data is kept in an uni-dimensional double[] *

* The use of this field is highly discouraged by end-user applications. *

* Note: this field is deprecated in order to remind application developers avoid its use. *

* If you cannot avoid access to the underlying data, please remember that it can be non-contiguous, chained or mapped, which * means that: *

  • you'd better obtain a reference to this internal data structure via method {@link Cells#data()} instead;
  • *
  • you must be sure to use methods {@link Array#_(int)} and {@link Matrix#_(int, int)} in order to guarantee you calculate * properly addresses of elements in the underlying data structure.
  • *

    * This internal data structure is exposed for convenience purposes only, given the fact that algorithms in general * handle arrays or matrices directly. It's recommended that application code never calculate indexes directly, but * employ Address mappings in order to perform this task. *

    * In particular, when employing f2j in order to translate algorithms from FORTRAN * into Java, the obtained code is 1-based indexed, like it is in FORTRAN, like this: *

         *    for (i = 1; i <= n; i++)
         * 
    * rather than 0-based, like it is in Java, like this: *
         *    for (i = 0; i < n; i++)
         * 
    * For this reason, you'd better let JQuantLib manage indexing. The only thing you need to adjust is direct access to * elements of arrays and matrices, converting things like a[i] to a.$[a._(i)] in case of arrays * and things like m[i][j] to m.$[m._(i,j)] in case of matrices. * * @see Array#_(int) * @see Matrix#_(int, int) */ @Deprecated public double[] $; /** * Builds a Storage of rows by cols * * @param rows is the number of rows * @param cols is the number of columns * @throws IllegalArgumentException if parameters are less than zero */ protected Cells( final int rows, final int cols, final T addr) { this.rows = rows; this.cols = cols; this.addr = addr; this.size = rows*cols; this.$ = new double[size]; } /** * Performs a shallow copy of another Cells instance *

    * This constructor accepts a custom Offset implementation, which is responsible for * mapping a virtual address map onto its physical representation on an already existing Cells. * * @param rows is the number of rows * @param cols is the number of columns * @param data is an existing data buffer * @param addr is an Address calculation policy responsible for mapping virtual addresses to physical addresses */ protected Cells( final int rows, final int cols, final double data[], final T addr) { this.rows = rows; this.cols = cols; this.$ = data; this.addr = addr; this.size = rows*cols; if (data.length != addr.rows()*addr.cols()) throw new IllegalArgumentException("declared dimension do not match underlying storage size"); } // // public methods // public final int rows() { return rows; } public final int columns() { return cols; } public final int cols() { return cols; } // FIXME: remove this public final int size() { return size; } public final boolean empty() { return size <= 0; } public final Set flags() { return addr.flags(); } public void requireFlags(final Set required, final String variable) { if (required.contains(Address.Flags.FORTRAN) != addr.isFortran()) { final String name = (variable==null) ? "variable" : (this.getClass().getSimpleName() + " " + variable); final String message = String.format(FORTRAN_ADDRESSING_EXPECTED, name); QL.error(String.format(FORTRAN_ADDRESSING_EXPECTED, name)); } } // // Overrides Object // @Override public Cells clone() { try { return (Cells) super.clone(); } catch (final CloneNotSupportedException e) { throw new LibraryException(e); } } //TODO: implement hashCode and equals // // @Override // public int hashCode() { // final int prime = 31; // int result = 1; // result = prime * result + cols; // result = prime * result + rows; // return result; // } // @Override // public boolean equals(Object obj) { // if (this == obj) // return true; // if (obj == null) // return false; // if (getClass() != obj.getClass()) // return false; // Cells other = (Cells) obj; // if (cols != other.cols) // return false; // if (rows != other.rows) // return false; // return true; // } }

    Ads help maintain this website.