001/* 002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. 003 * Copyright (C) 2006 - JScience (http://jscience.org/) 004 * All rights reserved. 005 * 006 * Permission to use, copy, modify, and distribute this software is 007 * freely granted, provided that this notice is preserved. 008 */ 009package org.jscience.mathematics.vector; 010 011import java.util.List; 012 013import javolution.context.ObjectFactory; 014import javolution.context.StackContext; 015import javolution.util.FastTable; 016import javolution.xml.XMLFormat; 017import javolution.xml.stream.XMLStreamException; 018 019import org.jscience.mathematics.structure.Field; 020 021/** 022 * <p> This class represents a dense vector.</p> 023 * 024 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 025 * @version 3.3, January 2, 2007 026 */ 027public final class DenseVector<F extends Field<F>> extends Vector<F> { 028 029 /** 030 * Holds the default XML representation for dense vectors. For example: 031 * [code] 032 * <DenseVector dimension="2"> 033 * <Rational value="1/3" /> 034 * <Rational value="3/5" /> 035 * </DenseVector>[/code] 036 */ 037 protected static final XMLFormat<DenseVector> XML = new XMLFormat<DenseVector>( 038 DenseVector.class) { 039 040 @Override 041 public DenseVector newInstance(Class<DenseVector> cls, InputElement xml) 042 throws XMLStreamException { 043 return FACTORY.object(); 044 } 045 046 @SuppressWarnings("unchecked") 047 @Override 048 public void read(InputElement xml, DenseVector V) 049 throws XMLStreamException { 050 int dimension = xml.getAttribute("dimension", 0); 051 for (int i=0; i < dimension; i++) { 052 V._elements.add(xml.getNext()); 053 } 054 if (xml.hasNext()) 055 throw new XMLStreamException("Too many elements"); 056 } 057 058 @Override 059 public void write(DenseVector V, OutputElement xml) 060 throws XMLStreamException { 061 int dimension = V._elements.size(); 062 xml.setAttribute("dimension", dimension); 063 for (int i = 0; i < dimension;) { 064 xml.add(V._elements.get(i++)); 065 } 066 } 067 }; 068 069 /** 070 * Holds the elements. 071 */ 072 final FastTable<F> _elements = new FastTable<F>(); 073 074 /** 075 * Returns a dense vector holding the specified elements. 076 * 077 * @param elements the vector elements. 078 * @return the vector having the specified elements. 079 */ 080 public static <F extends Field<F>> DenseVector<F> valueOf(F... elements) { 081 DenseVector<F> V = DenseVector.newInstance(); 082 for (int i=0, n=elements.length; i < n;) { 083 V._elements.add(elements[i++]); 084 } 085 return V; 086 } 087 088 /** 089 * Returns a dense vector holding the elements from the specified 090 * collection. 091 * 092 * @param elements the collection of vector elements. 093 * @return the vector having the specified elements. 094 */ 095 public static <F extends Field<F>> DenseVector<F> valueOf(List<F> elements) { 096 DenseVector<F> V = DenseVector.newInstance(); 097 V._elements.addAll(elements); 098 return V; 099 } 100 101 /** 102 * Returns a dense vector equivalent to the specified vector. 103 * 104 * @param that the vector to convert. 105 * @return <code>that</code> or a dense vector holding the same elements 106 * as the specified vector. 107 */ 108 public static <F extends Field<F>> DenseVector<F> valueOf(Vector<F> that) { 109 if (that instanceof DenseVector) return (DenseVector<F>) that; 110 DenseVector<F> V = DenseVector.newInstance(); 111 for (int i=0, n=that.getDimension(); i < n;) { 112 V. _elements.add(that.get(i++)); 113 } 114 return V; 115 } 116 117 @Override 118 public int getDimension() { 119 return _elements.size(); 120 } 121 122 @Override 123 public F get(int i) { 124 return _elements.get(i); 125 } 126 127 @Override 128 public DenseVector<F> opposite() { 129 DenseVector<F> V = DenseVector.newInstance(); 130 for (int i = 0, n = _elements.size(); i < n;) { 131 V._elements.add(_elements.get(i++).opposite()); 132 } 133 return V; 134 } 135 136 @Override 137 public DenseVector<F> plus(Vector<F> that) { 138 final int n = _elements.size(); 139 if (that.getDimension() != n) 140 throw new DimensionException(); 141 DenseVector<F> V = DenseVector.newInstance(); 142 for (int i = 0; i < n; i++) { 143 V._elements.add(_elements.get(i).plus(that.get(i))); 144 } 145 return V; 146 } 147 148 @Override 149 public DenseVector<F> minus(Vector<F> that) { // Returns more specialized type. 150 return this.plus(that.opposite()); 151 } 152 153 @Override 154 public DenseVector<F> times(F k) { 155 DenseVector<F> V = DenseVector.newInstance(); 156 for (int i = 0, n = _elements.size(); i < n;) { 157 V._elements.add(_elements.get(i++).times(k)); 158 } 159 return V; 160 } 161 162 @Override 163 public F times(Vector<F> that) { 164 final int n = _elements.size(); 165 if (that.getDimension() != n) 166 throw new DimensionException(); 167 StackContext.enter(); 168 try { // Reduces memory allocation / garbage collection. 169 F sum = _elements.get(0).times(that.get(0)); 170 for (int i = 1; i < n; i++) { 171 sum = sum.plus(_elements.get(i).times(that.get(i))); 172 } 173 return StackContext.outerCopy(sum); 174 } finally { 175 StackContext.exit(); 176 } 177 } 178 179 @SuppressWarnings("unchecked") 180 @Override 181 public DenseVector<F> copy() { 182 DenseVector<F> V = DenseVector.newInstance(); 183 for (F e : _elements) { 184 V._elements.add((F)e.copy()); 185 } 186 return V; 187 } 188 189 /////////////////////// 190 // Factory creation. // 191 /////////////////////// 192 193 @SuppressWarnings("unchecked") 194 static <F extends Field<F>> DenseVector<F> newInstance() { 195 return FACTORY.object(); 196 } 197 198 private static final ObjectFactory<DenseVector> FACTORY = new ObjectFactory<DenseVector>() { 199 @Override 200 protected DenseVector create() { 201 return new DenseVector(); 202 } 203 204 @Override 205 protected void cleanup(DenseVector vector) { 206 vector._elements.reset(); 207 } 208 }; 209 210 private DenseVector() { 211 } 212 213 private static final long serialVersionUID = 1L; 214 215 216}