/java/src/jmat/impl/MatrixJC.java
Java | 1199 lines | 1077 code | 100 blank | 22 comment | 308 complexity | 400ec8ac7d500a031a4735647b3caa6f MD5 | raw file
- /**
- *
- */
- package jmat.impl;
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.TreeSet;
- import java.util.Map.Entry;
-
- import jmat.intr.Matrix;
-
- /**
- * @author Aram Altschudjian
- *
- */
-
- public class MatrixJC implements Matrix{
- private int dimensions = 0;
- private ArrayList<Integer> sizes = null;
- private ArrayList<Object> data = null;
- private ArrayList<HashMap<String, Integer>> names = null;
- private int entries = 0;
- private Object defaultValue = 0;
-
- public MatrixJC(){
-
- }
-
- public MatrixJC(Integer... sizes){
- setSize(sizes);
- init(defaultValue);
- }
-
- public MatrixJC(ArrayList<Object> data){
- assign(data);
- }
-
- public MatrixJC(ArrayList<Object> data, ArrayList<Integer> sizes){
- this.data = data;
- setSize(sizes);
- }
-
- public MatrixJC(ArrayList<Object> data, Integer... sizes){
- this.data = data;
- setSize(sizes);
- }
-
- public void init(Object defaultValue, ArrayList<Integer> sizes){
- setSize(sizes);
- init(defaultValue);
- }
-
- public void init(Object defaultValue, Integer... sizes){
- setSize(sizes);
- init(defaultValue);
- }
-
- public void init(Object defaultValue){
- validate();
- this.defaultValue = defaultValue;
- entries = 0;
- data = new ArrayList<Object>(size(0));
- fill(0, data);
- }
-
- private void fill(int dimension, ArrayList<Object> data) {
- if(dimension + 1 == dimensions){
- for(int i = data.size(); i < size(dimension); ++i){
- data.add(defaultValue);
- }
- } else if(dimension + 1 < dimensions){
- for(int i = data.size(); i < size(dimension); ++i){
- ArrayList<Object> next = new ArrayList<Object>(size(dimension + 1));
- fill(dimension + 1, next);
- data.add(next);
- }
- } else{
- throw new IndexOutOfBoundsException();
- }
- }
-
- public void setDefault(Object defaultValue){
- this.defaultValue = defaultValue;
- }
-
- @SuppressWarnings("unchecked")
- public void data(Object data){
- if(data instanceof ArrayList){
- this.data = (ArrayList<Object>)data;
- } else if(data instanceof List){
- this.data = new ArrayList<Object>((List<Object>)data);
- } else{
- throw new IllegalArgumentException("Illegal data type.");
- }
- }
-
- public ArrayList<Object> data(){
- return data;
- }
-
- @SuppressWarnings("unchecked")
- public Object val(){
- if(entries() == 1){
- Object result = data;
- for(int i = 0; i < dimensions; ++i){
- result = ((ArrayList<Object>)result).get(0);
- }
- return result;
- } else{
- throw new UnsupportedOperationException("Value request for dimensions = " + dimensions + " and sizes " + size() + " not supported.");
- }
- }
-
- public boolean valid(){
- if(dimensions == 0 || sizes == null || sizes.size() != dimensions){
- return false;
- }
- return true;
- }
-
- public void reset(){
- dimensions = 0;
- sizes = null;
- data = null;
- names = null;
- entries = 0;
- }
-
- public int entries(){
- if(entries == 0){
- entries = 1;
- for(int i = 0; i < dimensions; ++i){
- entries *= sizes.get(i);
- }
- }
- return entries;
- }
-
- public ArrayList<Integer> indices(){
- ArrayList<Integer> indices = new ArrayList<Integer>(entries());
- for(int i = 0; i < entries(); ++i){
- indices.add(i);
- }
- return indices;
- }
-
- @SuppressWarnings("unchecked")
- public void assign(Object data){
- data(data);
- ArrayList<Integer> sizes = new ArrayList<Integer>();
- if(data != null){
- while(data instanceof ArrayList){
- int size = ((ArrayList<Integer>)data).size();
- if(size > 0){
- sizes.add(size);
- data = ((ArrayList<Integer>)data).get(0);
- if(data == null){
- break;
- }
- } else{
- break;
- }
- }
- }
- setSize(sizes);
- }
-
- public void assign(Matrix matrix){
- if(!(matrix instanceof MatrixJC)){
- throw new IllegalArgumentException("Assignment of different Matrix types is currently not supported.");
- } else{
- MatrixJC input = (MatrixJC)matrix;
- data(input.data());
- setSize(input.size());
- }
- }
-
- public Matrix get(Object... address){
- if(address.length == 1){
- return get(address[0]);
- } else{
- return get((Object)address);
- }
- }
-
- @SuppressWarnings("unchecked")
- public Matrix get(Object address){
- if(address instanceof List){
- // Multiple 1D-coordinates
- List<Object> list = (List<Object>)address;
- ArrayList<Object> results = new ArrayList<Object>(list.size());
- for(int i = 0; i < list.size(); ++i){
- results.add(fetch(new Address(this, list.get(i)), 0, data));
- }
- return new MatrixJC(results, results.size());
- } else{
- // One or more multi-dim coordinates
- Address jAddress = new Address(this, address);
- return new MatrixJC(assemble(jAddress, 0, data), jAddress.size());
- }
- }
-
- @SuppressWarnings("unchecked")
- private Object fetch(Address address, int dimension, ArrayList<Object> data) {
- if(dimension + 1 == dimensions){
- return data.get(address.get(dimension, 0));
- } else if(dimension + 1 < dimensions){
- return fetch(address, dimension + 1, (ArrayList<Object>)data.get(address.get(dimension, 0)));
- } else{
- throw new IllegalArgumentException("Dimension mismatch.");
- }
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> assemble(Address address, int dimension, ArrayList<Object> data) {
- ArrayList<Object> result = new ArrayList<Object>(address.size(dimension));
- if(dimension + 1 == dimensions){
- for(int i = 0; i < address.size(dimension); ++i){
- result.add(data.get(address.get(dimension, i)));
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < address.size(dimension); ++i){
- result.add(assemble(address, dimension + 1, (ArrayList<Object>)data.get(address.get(dimension, i))));
- }
- } else{
- throw new IllegalArgumentException("Dimension mismatch.");
- }
- return result;
- }
-
- @SuppressWarnings("unchecked")
- public void put(Object address, Object entry){
- Address jAddress = new Address(this, address);
- // Ensure capacity
- int[] maxima = jAddress.max();
- for(int i = 0; i < dimensions; ++i){
- int diff = maxima[i] - size(i) + 1;
- if(diff > 0){
- extend(i, diff);
- }
- }
- // Switching by entry type
- if(entry instanceof Matrix){
- // Multiple entries
- List<Object> list = ((Matrix)entry).list();
- // Make sure sizes match
- if(list.size() != jAddress.entries()){
- throw new IllegalArgumentException("Assignment size mismatch.");
- }
- // Distribute entries among addresses
- distribute(jAddress, 0, list, data);
- } else if(entry instanceof List){
- // Multiple entries
- List<Object> list = (List<Object>)entry;
- // Make sure sizes match
- if(list.size() != jAddress.entries()){
- throw new IllegalArgumentException("Assignment size mismatch.");
- }
- // Distribute entries among addresses
- distribute(jAddress, 0, list, data);
- } else{
- // Single entry
- place(jAddress, 0, entry, data);
- }
- }
-
- @SuppressWarnings("unchecked")
- private void place(Address address, int dimension, Object value, ArrayList<Object> data) {
- if(dimension + 1 == dimensions){
- data.set(address.get(dimension, 0), value);
- } else if(dimension + 1 < dimensions){
- place(address, dimension + 1, value, (ArrayList<Object>)data.get(address.get(dimension, 0)));
- } else{
- throw new IllegalArgumentException("Dimension mismatch.");
- }
- }
-
- @SuppressWarnings("unchecked")
- private void distribute(Address address, int dimension, List<Object> values, ArrayList<Object> data) {
- if(dimension + 1 == dimensions){
- if(address.size(dimension) != values.size()){
- throw new RuntimeException("Program logic error.");
- }
- for(int i = 0; i < address.size(dimension); ++i){
- data.set(address.get(dimension, i), values.get(i));
- }
- } else if(dimension + 1 < dimensions){
- int clusterSize = values.size() / address.size(dimension);
- int fromIndex = 0;
- int toIndex = clusterSize;
- for(int i = 0; i < address.size(dimension); ++i){
- distribute(address, dimension + 1, values.subList(fromIndex, toIndex), (ArrayList<Object>)data.get(address.get(dimension, i)));
- fromIndex = toIndex;
- toIndex += clusterSize;
- }
- } else{
- throw new IllegalArgumentException("Dimension mismatch.");
- }
- }
-
- public ArrayList<Integer> find(Object entry){
- ArrayList<Integer> results = new ArrayList<Integer>();
- find(0, new ArrayList<Integer>(), data, entry, results);
- return results;
- }
-
- @SuppressWarnings("unchecked")
- private void find(int dimension, ArrayList<Integer> address, ArrayList<Object> data, Object entry, ArrayList<Integer> results) {
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(i); ++i){
- if(data.get(i).equals(entry)){
- ArrayList<Integer> match = new ArrayList<Integer>(address);
- match.add(i);
- results.add(convert(match));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(i); ++i){
- ArrayList<Integer> next = new ArrayList<Integer>(address);
- next.add(i);
- find(dimension + 1, next, (ArrayList<Object>)data.get(i), entry, results);
- }
- } else{
- throw new IndexOutOfBoundsException();
- }
- }
-
- public ArrayList<Integer> nfind(Object entry){
- ArrayList<Integer> results = new ArrayList<Integer>();
- nfind(0, new ArrayList<Integer>(), data, entry, results);
- return results;
- }
-
- @SuppressWarnings("unchecked")
- private void nfind(int dimension, ArrayList<Integer> address, ArrayList<Object> data, Object entry, ArrayList<Integer> results) {
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(i); ++i){
- if(!data.get(i).equals(entry)){
- ArrayList<Integer> match = new ArrayList<Integer>(address);
- match.add(i);
- results.add(convert(match));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(i); ++i){
- ArrayList<Integer> next = new ArrayList<Integer>(address);
- next.add(i);
- find(dimension + 1, next, (ArrayList<Object>)data.get(i), entry, results);
- }
- } else{
- throw new IndexOutOfBoundsException();
- }
- }
-
- public int count(Object entry){
- return count(0, data, entry);
- }
-
- @SuppressWarnings("unchecked")
- private int count(int dimension, ArrayList<Object> data, Object entry) {
- int counter = 0;
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(data.get(i).equals(entry)){
- ++counter;
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- counter += count(dimension + 1, (ArrayList<Object>)data.get(i), entry);
- }
- } else{
- throw new IndexOutOfBoundsException();
- }
- return counter;
- }
-
- public void setDim(int dimensions){
- this.dimensions = dimensions;
- if(names == null){
- names = new ArrayList<HashMap<String, Integer>>(dimensions);
- } else{
- names.ensureCapacity(dimensions);
- }
- }
-
- public int getDim(){
- return dimensions;
- }
-
- public void setSize(ArrayList<Integer> sizes){
- this.sizes = sizes;
- setDim(this.sizes.size());
- entries = 0;
- }
-
- public void setSize(Integer... sizes){
- this.sizes = new ArrayList<Integer>(sizes.length);
- for(int i = 0; i < sizes.length; ++i){
- this.sizes.add(sizes[i]);
- }
- setDim(this.sizes.size());
- entries = 0;
- }
-
- public ArrayList<Integer> size(){
- return sizes;
- }
-
- public int size(int dimension){
- return sizes.get(dimension);
- }
-
- public ArrayList<Object> list(){
- ArrayList<Object> list = new ArrayList<Object>(entries());
- for(int i = 0; i < entries(); ++i){
- list.add(get(i).val());
- }
- return list;
- }
-
- public ArrayList<Object> unique(){
- TreeSet<Object> set = new TreeSet<Object>(list());
- Iterator<Object> iterator = set.iterator();
- ArrayList<Object> result = new ArrayList<Object>(set.size());
- while(iterator.hasNext()){
- result.add(iterator.next());
- }
- return result;
- }
-
- public boolean isEmpty(){
- return entries() == 0;
- }
-
- public boolean equals(MatrixJC candidate){
- return data.equals(candidate.data());
- }
-
- public boolean equals(Matrix candidate){
- if(candidate instanceof MatrixJC){
- return equals((MatrixJC)candidate);
- }
- boolean isEqual = entries() == candidate.entries() && size().equals(candidate.size());
- int i = 0;
- while(isEqual && i < entries()){
- isEqual = get(i).val().equals(candidate.get(i).val());
- ++i;
- }
- return isEqual;
- }
-
- public Object max(){
- Double result = max(0, data);
- if(result.intValue() == result.doubleValue()){
- return result.intValue();
- } else{
- return result;
- }
- }
-
- @SuppressWarnings("unchecked")
- private Double max(int dimension, ArrayList<Object> data){
- Double result = Double.NEGATIVE_INFINITY;
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(data.get(i) instanceof Number){
- result = java.lang.Math.max(result, ((Number)data.get(i)).doubleValue());
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result = java.lang.Math.max(result, max(dimension + 1, (ArrayList<Object>)data.get(i)));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public int maxIndex(){
- // This is not a performance-optimal implementation
- ArrayList<Object> elements = list();
- Double max = Double.NEGATIVE_INFINITY;
- int index = 0;
- Object element;
- for(int i = 0; i < entries(); ++i){
- element = elements.get(i);
- if(element instanceof Number && ((Number)element).doubleValue() > max){
- max = ((Number)element).doubleValue();
- index = i;
- }
- }
- return index;
- }
-
- public Object min(){
- Double result = min(0, data);
- if(result.intValue() == result.doubleValue()){
- return result.intValue();
- } else{
- return result;
- }
- }
-
- @SuppressWarnings("unchecked")
- private Double min(int dimension, ArrayList<Object> data){
- Double result = Double.POSITIVE_INFINITY;
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(data.get(i) instanceof Number){
- result = java.lang.Math.min(result, ((Number)data.get(i)).doubleValue());
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result = java.lang.Math.min(result, min(dimension + 1, (ArrayList<Object>)data.get(i)));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public int minIndex(){
- // This is not a performance-optimal implementation
- ArrayList<Object> elements = list();
- Double min = Double.POSITIVE_INFINITY;
- int index = 0;
- Object element;
- for(int i = 0; i < entries(); ++i){
- element = elements.get(i);
- if(element instanceof Number && ((Number)element).doubleValue() < min){
- min = ((Number)element).doubleValue();
- index = i;
- }
- }
- return index;
- }
-
- public Matrix sum(){
- if(dimensions == 2){
- return new MatrixJC(twoDSum());
- } else if(dimensions == 1){
- ArrayList<Object> sum = new ArrayList<Object>(1);
- sum.add(sumAll());
- return new MatrixJC(sum);
- } else{
- throw new UnsupportedOperationException("Currently can only form sum for 1- and 2-dimensional matrices.");
- }
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> twoDSum(){
- ArrayList<Object> result = new ArrayList<Object>(size(1));
- for(int i = 0; i < size(1); ++i){
- Double sum = 0.0;
- Object element;
- for(int j = 0; j < size(0); ++j){
- element = ((ArrayList<Object>)data.get(j)).get(i);
- if(element instanceof Number){
- sum += ((Number)element).doubleValue();
- }
- }
- if(sum.intValue() == sum.doubleValue()){
- result.add(sum.intValue());
- } else{
- result.add(sum);
- }
- }
- return result;
- }
-
- public Object sumAll(){
- Double result = sumAll(0, data);
- if(result.intValue() == result.doubleValue()){
- return result.intValue();
- } else{
- return result;
- }
- }
-
- @SuppressWarnings("unchecked")
- private Double sumAll(int dimension, ArrayList<Object> data){
- Double result = 0.0;
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(data.get(i) instanceof Number){
- result += ((Number)data.get(i)).doubleValue();
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result += sumAll(dimension + 1, (ArrayList<Object>)data.get(i));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public Matrix plus(Matrix matrix){
- if(!(matrix instanceof MatrixJC)){
- throw new IllegalArgumentException("Currently can only add matrices of the same implementation type.");
- } else if(!size().equals(matrix.size())){
- throw new IllegalArgumentException("Size mismatch between " + size() + " and " + matrix.size());
- } else{
- MatrixJC result = new MatrixJC(plus(0, data(), ((MatrixJC)matrix).data()));
- result.names = names;
- return result;
- }
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> plus(int dimension, ArrayList<Object> own, ArrayList<Object> other){
- ArrayList<Object> result = new ArrayList<Object>(size(dimension));
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(own.get(i) instanceof Number && other.get(i) instanceof Number){
- Double calc = ((Number)own.get(i)).doubleValue() + ((Number)other.get(i)).doubleValue();
- if(calc.intValue() == calc.doubleValue()){
- result.add(calc.intValue());
- } else{
- result.add(calc.doubleValue());
- }
- } else{
- result.add(own.get(i));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result.add(plus(dimension + 1, (ArrayList<Object>)own.get(i), (ArrayList<Object>)other.get(i)));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public Matrix plus(Number number){
- MatrixJC result = new MatrixJC(plus(0, data(), number));
- result.names = names;
- return result;
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> plus(int dimension, ArrayList<Object> own, Number number){
- ArrayList<Object> result = new ArrayList<Object>(size(dimension));
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(own.get(i) instanceof Number){
- Double calc = ((Number)own.get(i)).doubleValue() + number.doubleValue();
- if(calc.intValue() == calc.doubleValue()){
- result.add(calc.intValue());
- } else{
- result.add(calc.doubleValue());
- }
- } else{
- result.add(own.get(i));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result.add(plus(dimension + 1, (ArrayList<Object>)own.get(i), number));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public Matrix minus(Matrix matrix){
- if(!(matrix instanceof MatrixJC)){
- throw new IllegalArgumentException("Currently can only add matrices of the same implementation type.");
- } else if(!size().equals(matrix.size())){
- throw new IllegalArgumentException("Size mismatch between " + size() + " and " + matrix.size());
- } else{
- MatrixJC result = new MatrixJC(minus(0, data(), ((MatrixJC)matrix).data()));
- result.names = names;
- return result;
- }
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> minus(int dimension, ArrayList<Object> own, ArrayList<Object> other){
- ArrayList<Object> result = new ArrayList<Object>(size(dimension));
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(own.get(i) instanceof Number && other.get(i) instanceof Number){
- Double calc = ((Number)own.get(i)).doubleValue() - ((Number)other.get(i)).doubleValue();
- if(calc.intValue() == calc.doubleValue()){
- result.add(calc.intValue());
- } else{
- result.add(calc.doubleValue());
- }
- } else{
- result.add(own.get(i));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result.add(minus(dimension + 1, (ArrayList<Object>)own.get(i), (ArrayList<Object>)other.get(i)));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public Matrix minus(Number number){
- MatrixJC result = new MatrixJC(minus(0, data(), number));
- result.names = names;
- return result;
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> minus(int dimension, ArrayList<Object> own, Number number){
- ArrayList<Object> result = new ArrayList<Object>(size(dimension));
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(own.get(i) instanceof Number){
- Double calc = ((Number)own.get(i)).doubleValue() - number.doubleValue();
- if(calc.intValue() == calc.doubleValue()){
- result.add(calc.intValue());
- } else{
- result.add(calc.doubleValue());
- }
- } else{
- result.add(own.get(i));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result.add(minus(dimension + 1, (ArrayList<Object>)own.get(i), number));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public Matrix mult(Matrix matrix){
- if(!(matrix instanceof MatrixJC)){
- throw new IllegalArgumentException("Currently can only add matrices of the same implementation type.");
- } else if(!size().equals(matrix.size())){
- throw new IllegalArgumentException("Size mismatch between " + size() + " and " + matrix.size());
- } else{
- MatrixJC result = new MatrixJC(mult(0, data(), ((MatrixJC)matrix).data()));
- result.names = names;
- return result;
- }
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> mult(int dimension, ArrayList<Object> own, ArrayList<Object> other){
- ArrayList<Object> result = new ArrayList<Object>(size(dimension));
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(own.get(i) instanceof Number && other.get(i) instanceof Number){
- Double calc = ((Number)own.get(i)).doubleValue() * ((Number)other.get(i)).doubleValue();
- if(calc.intValue() == calc.doubleValue()){
- result.add(calc.intValue());
- } else{
- result.add(calc.doubleValue());
- }
- } else{
- result.add(own.get(i));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result.add(mult(dimension + 1, (ArrayList<Object>)own.get(i), (ArrayList<Object>)other.get(i)));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public Matrix mult(Number number){
- MatrixJC result = new MatrixJC(mult(0, data(), number));
- result.names = names;
- return result;
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> mult(int dimension, ArrayList<Object> own, Number number){
- ArrayList<Object> result = new ArrayList<Object>(size(dimension));
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(own.get(i) instanceof Number){
- Double calc = ((Number)own.get(i)).doubleValue() * number.doubleValue();
- if(calc.intValue() == calc.doubleValue()){
- result.add(calc.intValue());
- } else{
- result.add(calc.doubleValue());
- }
- } else{
- result.add(own.get(i));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result.add(mult(dimension + 1, (ArrayList<Object>)own.get(i), number));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public Matrix div(Matrix matrix){
- if(!(matrix instanceof MatrixJC)){
- throw new IllegalArgumentException("Currently can only add matrices of the same implementation type.");
- } else if(!size().equals(matrix.size())){
- throw new IllegalArgumentException("Size mismatch between " + size() + " and " + matrix.size());
- } else{
- MatrixJC result = new MatrixJC(div(0, data(), ((MatrixJC)matrix).data()));
- result.names = names;
- return result;
- }
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> div(int dimension, ArrayList<Object> own, ArrayList<Object> other){
- ArrayList<Object> result = new ArrayList<Object>(size(dimension));
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(own.get(i) instanceof Number && other.get(i) instanceof Number){
- Double calc = ((Number)own.get(i)).doubleValue() / ((Number)other.get(i)).doubleValue();
- if(calc.intValue() == calc.doubleValue()){
- result.add(calc.intValue());
- } else{
- result.add(calc.doubleValue());
- }
- } else{
- result.add(own.get(i));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result.add(div(dimension + 1, (ArrayList<Object>)own.get(i), (ArrayList<Object>)other.get(i)));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public Matrix div(Number number){
- MatrixJC result = new MatrixJC(div(0, data(), number));
- result.names = names;
- return result;
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> div(int dimension, ArrayList<Object> own, Number number){
- ArrayList<Object> result = new ArrayList<Object>(size(dimension));
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(own.get(i) instanceof Number){
- Double calc = ((Number)own.get(i)).doubleValue() / number.doubleValue();
- if(calc.intValue() == calc.doubleValue()){
- result.add(calc.intValue());
- } else{
- result.add(calc.doubleValue());
- }
- } else{
- result.add(own.get(i));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result.add(div(dimension + 1, (ArrayList<Object>)own.get(i), number));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public Matrix log(){
- MatrixJC result = new MatrixJC(log(0, data()));
- result.names = names;
- return result;
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> log(int dimension, ArrayList<Object> own){
- ArrayList<Object> result = new ArrayList<Object>(size(dimension));
- if(dimension + 1 == dimensions){
- for(int i = 0; i < size(dimension); ++i){
- if(own.get(i) instanceof Number){
- result.add(java.lang.Math.log(((Number)own.get(i)).doubleValue()));
- } else{
- result.add(own.get(i));
- }
- }
- } else if(dimension + 1 < dimensions){
- for(int i = 0; i < size(dimension); ++i){
- result.add(log(dimension + 1, (ArrayList<Object>)own.get(i)));
- }
- } else{
- throw new IndexOutOfBoundsException("Should not happen.");
- }
- return result;
- }
-
- public Matrix subFrom(Number minuend){
- MatrixJC result = new MatrixJC();
- result.init(minuend, size());
- result.names = names;
- return result.minus(this);
- }
-
- public void extend(int dimension){
- extend(dimension, 1);
- }
-
- public void extend(int dimension, int amount){
- sizes.set(dimension, sizes.get(dimension) + amount);
- enlarge(dimension, 0, data, amount);
- entries = 0;
- }
-
- @SuppressWarnings("unchecked")
- private void enlarge(int goal, int current, ArrayList<Object> data, int amount) {
- if(current == goal){
- data.ensureCapacity(data.size() + amount);
- fill(current, data);
- } else if(current < goal){
- for(int i = 0; i < size(current); ++i){
- enlarge(goal, current + 1, (ArrayList<Object>)data.get(i), amount);
- }
- } else{
- throw new IndexOutOfBoundsException();
- }
- }
-
- @SuppressWarnings("unchecked")
- public void delete(Object address){
- if(isAll(address)){
- // Set all entries to 'null', but keep structure and name resolution.
- // For a total reset, use reset() instead.
- data = null;
- init(defaultValue);
- } else if(address instanceof ArrayList){
- entries = 0;
- ArrayList<Object> list = (ArrayList<Object>)address;
- if(list.size() != dimensions){
- throw new IllegalArgumentException("Dimension mismatch.");
- }
- for(int i = list.size() - 1; i >= 0; --i){
- if(!isAll(list.get(i))){
- delete(i, list.get(i));
- }
- }
- } else{
- throw new IllegalArgumentException("Address format mismatch.");
- }
- }
-
- public void delete(Object... address){
- entries = 0;
- if(address.length != dimensions){
- throw new IllegalArgumentException("Dimension mismatch.");
- }
- for(int i = address.length - 1; i >= 0; --i){
- if(!isAll(address[i])){
- delete(i, address[i]);
- }
- }
- }
-
- public void delete(int dimension, Object... address){
- delete(dimension, (Object)address);
- }
-
- @SuppressWarnings("unchecked")
- public void delete(int dimension, Object address){
- entries = 0;
- ArrayList<Integer> indices;
- if(isAll(address)){
- delete(all);
- return;
- } else if(address instanceof Integer){
- indices = new ArrayList<Integer>(1);
- int index = (Integer)address;
- indices.add(index < 0 ? size(dimension) + index : index);
- } else if(address instanceof String){
- indices = new ArrayList<Integer>(1);
- indices.add(resolve(dimension, (String)address));
- } else if(address instanceof Object[]){
- Object[] array = (Object[])address;
- indices = new ArrayList<Integer>(array.length);
- for(int i = 0; i < array.length; ++i){
- if(array[i] instanceof Integer){
- indices.add((Integer)array[i]);
- } else if(array[i] instanceof String){
- indices.add(resolve(dimension, (String)array[i]));
- } else{
- throw new IllegalArgumentException("Illegal index format.");
- }
- }
- } else if(address instanceof List){
- List<Object> list = (List<Object>)address;
- indices = new ArrayList<Integer>(list.size());
- for(int i = 0; i < list.size(); ++i){
- if(list.get(i) instanceof Integer){
- int index = (Integer)list.get(i);
- indices.add(index < 0 ? size(dimension) + index : index);
- } else if(list.get(i) instanceof String){
- indices.add(resolve(dimension, (String)list.get(i)));
- } else{
- throw new IllegalArgumentException("Illegal index format.");
- }
- }
- } else{
- throw new IllegalArgumentException("Illegal index format.");
- }
- purge(dimension, 0, indices, data);
- }
-
- @SuppressWarnings("unchecked")
- private void purge(int goal, int current, ArrayList<Integer> indices, ArrayList<Object> data) {
- if(current == goal){
- for(int i = 0; i < indices.size(); ++i){
- data.remove(indices.get(i));
- fixNames(goal, indices.get(i));
- }
- sizes.set(current, sizes.get(current) - indices.size());
- } else if(current < goal){
- for(int i = 0; i < size(current); ++i){
- purge(goal, current + 1, indices, (ArrayList<Object>)data.get(i));
- }
- } else{
- throw new IllegalArgumentException("Dimension mismatch.");
- }
- }
-
- private void fixNames(int dimension, int removed) {
- if(names == null || getNames(dimension) == null){
- return;
- }
- Iterator<Entry<String, Integer>> iterator = getNames(dimension).entrySet().iterator();
- while(iterator.hasNext()){
- Entry<String, Integer> entry = iterator.next();
- if(entry.getValue() == removed){
- iterator.remove();
- } else if(entry.getValue() > removed){
- entry.setValue(entry.getValue() - 1);
- }
- }
- }
-
- public void setOrder(int dimension, ArrayList<Integer> order){
- setOrder(dimension, order.toArray(new Integer[0]));
- }
-
- public void setOrder(int dimension, Integer... order){
- int size = size(dimension);
- if(order.length != size){
- throw new IllegalArgumentException("Please supply order indices for all elements of the dimension.");
- }
- int diff = 0;
- for(int i = 0; i < size; ++i){
- if(order[i] - size + 1 > diff){
- diff = order[i] - size + 1;
- }
- }
- if(diff > 0){
- extend(dimension, diff);
- }
- data = reorder(dimension, 0, order, data);
- }
-
- @SuppressWarnings("unchecked")
- private ArrayList<Object> reorder(int goal, int current, Integer[] order, ArrayList<Object> data) {
- ArrayList<Object> result = new ArrayList<Object>(size(current));
- if(current == goal){
- for(int i = 0; i < order.length; ++i){
- result.set(order[i], data.get(i));
- }
- } else if(current < goal){
- for(int i = 0; i < size(current); ++i){
- result.add(reorder(goal, current + 1, order, (ArrayList<Object>)data.get(i)));
- }
- } else{
- throw new IndexOutOfBoundsException();
- }
- return result;
- }
-
- public void addDim(int size, int index){
- entries = 0;
- ArrayList<Object> newData = new ArrayList<Object>(size);
- for(int i = 0; i < size; ++i){
- if(i == index){
- newData.add(data);
- } else{
- newData.add(null);
- }
- }
- ++dimensions;
- ArrayList<Integer> newSizes = new ArrayList<Integer>(dimensions);
- newSizes.add(size);
- newSizes.addAll(sizes);
- data = newData;
- sizes = newSizes;
- }
-
- public void setName(int dimension, int index, String name){
- if(names == null){
- names = new ArrayList<HashMap<String,Integer>>(dimensions);
- }
- HashMap<String, Integer> map = names.get(dimension);
- if(map == null){
- map = new HashMap<String, Integer>(sizes.get(dimension));
- names.set(dimension, map);
- }
- map.put(name, index);
- }
-
- public void setNames(int dimension, HashMap<String, Integer> nameToIndexMap){
- if(names == null){
- names = new ArrayList<HashMap<String,Integer>>(dimensions);
- }
- HashMap<String, Integer> map = names.get(dimension);
- if(map == null){
- names.set(dimension, nameToIndexMap);
- } else{
- map.putAll(nameToIndexMap);
- }
- }
-
- public HashMap<String, Integer> getNames(int dimension){
- return names.get(dimension);
- }
-
- public int resolve(int dimension, String name){
- return names.get(dimension).get(name);
- }
-
- public boolean isAll(Object candidate) {
- if(candidate instanceof Integer){
- return (Integer)candidate == Matrix.all;
- }
- return false;
- }
-
- public Integer[] convert(int address){
- Integer[] coordinates = new Integer[dimensions];
- int div = 1;
- int mod = 1;
- for(int i = 0; i < dimensions; ++i){
- mod *= size(i);
- coordinates[i] = (address % mod) / div;
- div = mod;
- }
- return coordinates;
- }
-
- public int convert(ArrayList<Object> address){
- return convert(address.toArray());
- }
-
- public int convert(Object... address){
- Integer[] coordinates;
- if(address instanceof Integer[]){
- coordinates = (Integer[])address;
- } else{
- throw new IllegalArgumentException("Address format mismatch");
- }
- int index = 0;
- int dimensionSize = 1;
- for(int i = 0; i < coordinates.length; ++i){
- index += (coordinates[i] < 0 ? (size(i) + coordinates[i]) * dimensionSize : coordinates[i] * dimensionSize);
- dimensionSize *= size(i);
- }
- return index;
- }
-
- private void validate(){
- if(!valid()){
- throw new RuntimeException("Inconsistent or uninitialized structure description.");
- }
- }
-
- public String toString(){
- if(data != null){
- return data.toString();
- } else{
- throw new RuntimeException("Requesting String representation of an uninitialized structure.");
- }
- }
- }