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}