~ubuntu-branches/ubuntu/oneiric/commons-math/oneiric

« back to all changes in this revision

Viewing changes to src/main/java/org/apache/commons/math/linear/OpenMapRealVector.java

  • Committer: Bazaar Package Importer
  • Author(s): Damien Raude-Morvan
  • Date: 2009-08-22 01:13:25 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090822011325-hi4peq1ua5weguwn
Tags: 2.0-1
* New upstream release.
* Set Maintainer field to Debian Java Team
* Add myself as Uploaders
* Switch to Quilt patch system:
  - Refresh all patchs
  - Remove B-D on dpatch, Add B-D on quilt
  - Include patchsys-quilt.mk in debian/rules
* Bump Standards-Version to 3.8.3:
  - Add a README.source to describe patch system
* Maven POMs:
  - Add a Build-Depends-Indep dependency on maven-repo-helper
  - Use mh_installpom and mh_installjar to install the POM and the jar to the
    Maven repository
* Use default-jdk/jre:
  - Depends on java5-runtime-headless
  - Build-Depends on default-jdk
  - Use /usr/lib/jvm/default-java as JAVA_HOME
* Move api documentation to /usr/share/doc/libcommons-math-java/api
* Build-Depends on junit4 instead of junit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
 
3
 * contributor license agreements.  See the NOTICE file distributed with
 
4
 * this work for additional information regarding copyright ownership.
 
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
6
 * (the "License"); you may not use this file except in compliance with
 
7
 * the License.  You may obtain a copy of the License at
 
8
 *
 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
11
 * Unless required by applicable law or agreed to in writing, software
 
12
 * distributed under the License is distributed on an "AS IS" BASIS,
 
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
 * See the License for the specific language governing permissions and
 
15
 * limitations under the License.
 
16
 */
 
17
package org.apache.commons.math.linear;
 
18
 
 
19
import java.io.Serializable;
 
20
 
 
21
import org.apache.commons.math.MathRuntimeException;
 
22
import org.apache.commons.math.util.OpenIntToDoubleHashMap;
 
23
import org.apache.commons.math.util.OpenIntToDoubleHashMap.Iterator;
 
24
 
 
25
/**
 
26
 * This class implements the {@link RealVector} interface with a {@link OpenIntToDoubleHashMap} backing store.
 
27
 * @version $Revision: 800111 $ $Date: 2009-08-02 13:23:05 -0400 (Sun, 02 Aug 2009) $
 
28
 * @since 2.0
 
29
*/
 
30
public class OpenMapRealVector implements SparseRealVector, Serializable {
 
31
 
 
32
    /** Serializable version identifier. */
 
33
    private static final long serialVersionUID = 8772222695580707260L;
 
34
 
 
35
    /** Default Tolerance for having a value considered zero. */
 
36
    public static final double DEFAULT_ZERO_TOLERANCE = 1.0e-12;
 
37
 
 
38
    /** Entries of the vector. */
 
39
    private final OpenIntToDoubleHashMap entries;
 
40
 
 
41
    /** Dimension of the vector. */
 
42
    private final int virtualSize;
 
43
 
 
44
    /** Tolerance for having a value considered zero. */
 
45
    private double epsilon;
 
46
 
 
47
    /**
 
48
     * Build a 0-length vector.
 
49
     * <p>Zero-length vectors may be used to initialized construction of vectors
 
50
     * by data gathering. We start with zero-length and use either the {@link
 
51
     * #OpenMapRealVector(OpenMapRealVector, int)} constructor
 
52
     * or one of the <code>append</code> method ({@link #append(double)}, {@link
 
53
     * #append(double[])}, {@link #append(RealVector)}) to gather data
 
54
     * into this vector.</p>
 
55
     */
 
56
    public OpenMapRealVector() {
 
57
        this(0, DEFAULT_ZERO_TOLERANCE);
 
58
    }
 
59
 
 
60
    /**
 
61
     * Construct a (dimension)-length vector of zeros.
 
62
     * @param dimension size of the vector
 
63
     */
 
64
    public OpenMapRealVector(int dimension) {
 
65
        this(dimension, DEFAULT_ZERO_TOLERANCE);
 
66
    }
 
67
 
 
68
    /**
 
69
     * Construct a (dimension)-length vector of zeros, specifying zero tolerance.
 
70
     * @param dimension Size of the vector
 
71
     * @param epsilon The tolerance for having a value considered zero
 
72
     */
 
73
    public OpenMapRealVector(int dimension, double epsilon) {
 
74
        virtualSize = dimension;
 
75
        entries = new OpenIntToDoubleHashMap(0.0);
 
76
        this.epsilon = epsilon;
 
77
    }
 
78
 
 
79
    /**
 
80
     * Build a resized vector, for use with append.
 
81
     * @param v The original vector
 
82
     * @param resize The amount to resize it
 
83
     */
 
84
    protected OpenMapRealVector(OpenMapRealVector v, int resize) {
 
85
        virtualSize = v.getDimension() + resize;
 
86
        entries = new OpenIntToDoubleHashMap(v.entries);
 
87
        epsilon = v.getEpsilon();
 
88
    }
 
89
 
 
90
    /**
 
91
     * Build a vector with known the sparseness (for advanced use only).
 
92
     * @param dimension The size of the vector
 
93
     * @param expectedSize The expected number of non-zero entries
 
94
     */
 
95
    public OpenMapRealVector(int dimension, int expectedSize) {
 
96
        this(dimension, expectedSize, DEFAULT_ZERO_TOLERANCE);
 
97
    }
 
98
 
 
99
    /**
 
100
     * Build a vector with known the sparseness and zero tolerance setting (for advanced use only).
 
101
     * @param dimension The size of the vector
 
102
     * @param expectedSize The expected number of non-zero entries
 
103
     * @param epsilon The tolerance for having a value considered zero
 
104
     */
 
105
    public OpenMapRealVector(int dimension, int expectedSize, double epsilon) {
 
106
        virtualSize = dimension;
 
107
        entries = new OpenIntToDoubleHashMap(expectedSize, 0.0);
 
108
        this.epsilon = epsilon;
 
109
    }
 
110
 
 
111
    /**
 
112
     * Create from a double array.
 
113
     * Only non-zero entries will be stored
 
114
     * @param values The set of values to create from
 
115
     */
 
116
    public OpenMapRealVector(double[] values) {
 
117
        this(values, DEFAULT_ZERO_TOLERANCE);
 
118
    }
 
119
 
 
120
    /**
 
121
     * Create from a double array, specifying zero tolerance.
 
122
     * Only non-zero entries will be stored
 
123
     * @param values The set of values to create from
 
124
     * @param epsilon The tolerance for having a value considered zero
 
125
     */
 
126
    public OpenMapRealVector(double[] values, double epsilon) {
 
127
        virtualSize = values.length;
 
128
        entries = new OpenIntToDoubleHashMap(0.0);
 
129
        this.epsilon = epsilon;
 
130
        for (int key = 0; key < values.length; key++) {
 
131
            double value = values[key];
 
132
            if (!isZero(value)) {
 
133
                entries.put(key, value);
 
134
            }
 
135
        }
 
136
    }
 
137
 
 
138
    /**
 
139
     * Create from a Double array.
 
140
     * Only non-zero entries will be stored
 
141
     * @param values The set of values to create from
 
142
     */
 
143
    public OpenMapRealVector(Double[] values) {
 
144
        this(values, DEFAULT_ZERO_TOLERANCE);
 
145
    }
 
146
 
 
147
    /**
 
148
     * Create from a Double array.
 
149
     * Only non-zero entries will be stored
 
150
     * @param values The set of values to create from
 
151
     * @param epsilon The tolerance for having a value considered zero
 
152
     */
 
153
    public OpenMapRealVector(Double[] values, double epsilon) {
 
154
        virtualSize = values.length;
 
155
        entries = new OpenIntToDoubleHashMap(0.0);
 
156
        this.epsilon = epsilon;
 
157
        for (int key = 0; key < values.length; key++) {
 
158
            double value = values[key].doubleValue();
 
159
            if (!isZero(value)) {
 
160
                entries.put(key, value);
 
161
            }
 
162
        }
 
163
    }
 
164
 
 
165
    /**
 
166
     * Copy constructor.
 
167
     * @param v The instance to copy from
 
168
     */
 
169
    public OpenMapRealVector(OpenMapRealVector v) {
 
170
        virtualSize = v.getDimension();
 
171
        entries = new OpenIntToDoubleHashMap(v.getEntries());
 
172
        epsilon = v.getEpsilon();
 
173
    }
 
174
 
 
175
    /**
 
176
     * Generic copy constructor.
 
177
     * @param v The instance to copy from
 
178
     */
 
179
    public OpenMapRealVector(RealVector v) {
 
180
        virtualSize = v.getDimension();
 
181
        entries = new OpenIntToDoubleHashMap(0.0);
 
182
        epsilon = DEFAULT_ZERO_TOLERANCE;
 
183
        for (int key = 0; key < virtualSize; key++) {
 
184
            double value = v.getEntry(key);
 
185
            if (!isZero(value)) {
 
186
                entries.put(key, value);
 
187
            }
 
188
        }
 
189
    }
 
190
 
 
191
    /**
 
192
     * Get the entries of this instance.
 
193
     * @return entries of this instance
 
194
     */
 
195
    private OpenIntToDoubleHashMap getEntries() {
 
196
        return entries;
 
197
    }
 
198
 
 
199
    /**
 
200
     * Determine if this value is zero.
 
201
     * @param value The value to test
 
202
     * @return <code>true</code> if this value is zero, <code>false</code> otherwise
 
203
     */
 
204
    protected boolean isZero(double value) {
 
205
        return value > -epsilon && value < epsilon;
 
206
    }
 
207
 
 
208
    /**
 
209
     * Get the tolerance for having a value considered zero.
 
210
     * @return The test range for testing if a value is zero
 
211
     */
 
212
    public double getEpsilon() {
 
213
        return epsilon;
 
214
    }
 
215
 
 
216
    /**
 
217
     * Set the tolerance for having a value considered zero.
 
218
     * @param epsilon The test range for testing if a value is zero
 
219
     */
 
220
    public void setEpsilon(double epsilon) {
 
221
        this.epsilon = epsilon;
 
222
    }
 
223
 
 
224
    /** {@inheritDoc} */
 
225
    public OpenMapRealVector add(RealVector v) throws IllegalArgumentException {
 
226
        checkVectorDimensions(v.getDimension());
 
227
        if (v instanceof OpenMapRealVector) {
 
228
            return add((OpenMapRealVector) v);
 
229
        }
 
230
        return add(v.getData());
 
231
    }
 
232
 
 
233
    /**
 
234
     * Optimized method to add two OpenMapRealVectors.
 
235
     * @param v Vector to add with
 
236
     * @return The sum of <code>this</code> with <code>v</code>
 
237
     * @throws IllegalArgumentException If the dimensions don't match
 
238
     */
 
239
    public OpenMapRealVector add(OpenMapRealVector v) throws IllegalArgumentException{
 
240
        checkVectorDimensions(v.getDimension());
 
241
        OpenMapRealVector res = copy();
 
242
        Iterator iter = v.getEntries().iterator();
 
243
        while (iter.hasNext()) {
 
244
            iter.advance();
 
245
            int key = iter.key();
 
246
            if (entries.containsKey(key)) {
 
247
                res.setEntry(key, entries.get(key) + iter.value());
 
248
            } else {
 
249
                res.setEntry(key, iter.value());
 
250
            }
 
251
        }
 
252
        return res;
 
253
    }
 
254
 
 
255
    /** {@inheritDoc} */
 
256
    public OpenMapRealVector add(double[] v) throws IllegalArgumentException {
 
257
        checkVectorDimensions(v.length);
 
258
        OpenMapRealVector res = new OpenMapRealVector(getDimension());
 
259
        for (int i = 0; i < v.length; i++) {
 
260
            res.setEntry(i, v[i] + getEntry(i));
 
261
        }
 
262
        return res;
 
263
    }
 
264
 
 
265
    /**
 
266
     * Optimized method to append a OpenMapRealVector.
 
267
     * @param v vector to append
 
268
     * @return The result of appending <code>v</code> to self
 
269
     */
 
270
    public OpenMapRealVector append(OpenMapRealVector v) {
 
271
        OpenMapRealVector res = new OpenMapRealVector(this, v.getDimension());
 
272
        Iterator iter = v.entries.iterator();
 
273
        while (iter.hasNext()) {
 
274
            iter.advance();
 
275
            res.setEntry(iter.key() + virtualSize, iter.value());
 
276
        }
 
277
        return res;
 
278
    }
 
279
 
 
280
    /** {@inheritDoc} */
 
281
    public OpenMapRealVector append(RealVector v) {
 
282
        if (v instanceof OpenMapRealVector) {
 
283
            return append((OpenMapRealVector) v);
 
284
        }
 
285
        return append(v.getData());
 
286
    }
 
287
 
 
288
    /** {@inheritDoc} */
 
289
    public OpenMapRealVector append(double d) {
 
290
        OpenMapRealVector res = new OpenMapRealVector(this, 1);
 
291
        res.setEntry(virtualSize, d);
 
292
        return res;
 
293
    }
 
294
 
 
295
    /** {@inheritDoc} */
 
296
    public OpenMapRealVector append(double[] a) {
 
297
        OpenMapRealVector res = new OpenMapRealVector(this, a.length);
 
298
        for (int i = 0; i < a.length; i++) {
 
299
            res.setEntry(i + virtualSize, a[i]);
 
300
        }
 
301
        return res;
 
302
    }
 
303
 
 
304
    /** {@inheritDoc} */
 
305
    public OpenMapRealVector copy() {
 
306
        return new OpenMapRealVector(this);
 
307
    }
 
308
 
 
309
    /** {@inheritDoc} */
 
310
    public double dotProduct(RealVector v) throws IllegalArgumentException {
 
311
        checkVectorDimensions(v.getDimension());
 
312
        double res = 0;
 
313
        Iterator iter = entries.iterator();
 
314
        while (iter.hasNext()) {
 
315
            iter.advance();
 
316
            res += v.getEntry(iter.key()) * iter.value();
 
317
        }
 
318
        return res;
 
319
    }
 
320
 
 
321
    /** {@inheritDoc} */
 
322
    public double dotProduct(double[] v) throws IllegalArgumentException {
 
323
        checkVectorDimensions(v.length);
 
324
        double res = 0;
 
325
        Iterator iter = entries.iterator();
 
326
        while (iter.hasNext()) {
 
327
            int idx = iter.key();
 
328
            double value = 0;
 
329
            if (idx < v.length) {
 
330
                value = v[idx];
 
331
            }
 
332
            res += value * iter.value();
 
333
        }
 
334
        return res;
 
335
    }
 
336
 
 
337
    /** {@inheritDoc} */
 
338
    public OpenMapRealVector ebeDivide(RealVector v) throws IllegalArgumentException {
 
339
        checkVectorDimensions(v.getDimension());
 
340
        OpenMapRealVector res = new OpenMapRealVector(this);
 
341
        Iterator iter = res.entries.iterator();
 
342
        while (iter.hasNext()) {
 
343
            iter.advance();
 
344
            res.setEntry(iter.key(), iter.value() / v.getEntry(iter.key()));
 
345
        }
 
346
        return res;
 
347
    }
 
348
 
 
349
    /** {@inheritDoc} */
 
350
    public OpenMapRealVector ebeDivide(double[] v) throws IllegalArgumentException {
 
351
        checkVectorDimensions(v.length);
 
352
        OpenMapRealVector res = new OpenMapRealVector(this);
 
353
        Iterator iter = res.entries.iterator();
 
354
        while (iter.hasNext()) {
 
355
            iter.advance();
 
356
            res.setEntry(iter.key(), iter.value() / v[iter.key()]);
 
357
        }
 
358
        return res;
 
359
    }
 
360
 
 
361
    /** {@inheritDoc} */
 
362
    public OpenMapRealVector ebeMultiply(RealVector v) throws IllegalArgumentException {
 
363
        checkVectorDimensions(v.getDimension());
 
364
        OpenMapRealVector res = new OpenMapRealVector(this);
 
365
        Iterator iter = res.entries.iterator();
 
366
        while (iter.hasNext()) {
 
367
            iter.advance();
 
368
            res.setEntry(iter.key(), iter.value() * v.getEntry(iter.key()));
 
369
        }
 
370
        return res;
 
371
    }
 
372
 
 
373
    /** {@inheritDoc} */
 
374
    public OpenMapRealVector ebeMultiply(double[] v) throws IllegalArgumentException {
 
375
        checkVectorDimensions(v.length);
 
376
        OpenMapRealVector res = new OpenMapRealVector(this);
 
377
        Iterator iter = res.entries.iterator();
 
378
        while (iter.hasNext()) {
 
379
            iter.advance();
 
380
            res.setEntry(iter.key(), iter.value() * v[iter.key()]);
 
381
        }
 
382
        return res;
 
383
    }
 
384
 
 
385
    /** {@inheritDoc} */
 
386
    public OpenMapRealVector getSubVector(int index, int n) throws MatrixIndexException {
 
387
        checkIndex(index);
 
388
        checkIndex(index + n - 1);
 
389
        OpenMapRealVector res = new OpenMapRealVector(n);
 
390
        int end = index + n;
 
391
        Iterator iter = entries.iterator();
 
392
        while (iter.hasNext()) {
 
393
            iter.advance();
 
394
            int key = iter.key();
 
395
            if (key >= index && key < end) {
 
396
                res.setEntry(key - index, iter.value());
 
397
            }
 
398
        }
 
399
        return res;
 
400
    }
 
401
 
 
402
    /** {@inheritDoc} */
 
403
    public double[] getData() {
 
404
        double[] res = new double[virtualSize];
 
405
        Iterator iter = entries.iterator();
 
406
        while (iter.hasNext()) {
 
407
            iter.advance();
 
408
            res[iter.key()] = iter.value();
 
409
        }
 
410
        return res;
 
411
    }
 
412
 
 
413
    /** {@inheritDoc} */
 
414
    public int getDimension() {
 
415
        return virtualSize;
 
416
    }
 
417
 
 
418
    /**
 
419
     * Optimized method to compute distance.
 
420
     * @param v The vector to compute distance to
 
421
     * @return The distance from <code>this</code> and <code>v</code>
 
422
     * @throws IllegalArgumentException If the dimensions don't match
 
423
     */
 
424
    public double getDistance(OpenMapRealVector v) throws IllegalArgumentException {
 
425
        Iterator iter = entries.iterator();
 
426
        double res = 0;
 
427
        while (iter.hasNext()) {
 
428
            iter.advance();
 
429
            int key = iter.key();
 
430
            double delta;
 
431
            delta = iter.value() - v.getEntry(key);
 
432
            res += delta * delta;
 
433
        }
 
434
        iter = v.getEntries().iterator();
 
435
        while (iter.hasNext()) {
 
436
            iter.advance();
 
437
            int key = iter.key();
 
438
            if (!entries.containsKey(key)) {
 
439
                final double value = iter.value();
 
440
                res += value * value;
 
441
            }
 
442
        }
 
443
        return Math.sqrt(res);
 
444
    }
 
445
 
 
446
    /** {@inheritDoc} */
 
447
    public double getDistance(RealVector v) throws IllegalArgumentException {
 
448
        checkVectorDimensions(v.getDimension());
 
449
        if (v instanceof OpenMapRealVector) {
 
450
            return getDistance((OpenMapRealVector) v);
 
451
        }
 
452
        return getDistance(v.getData());
 
453
    }
 
454
 
 
455
    /** {@inheritDoc} */
 
456
    public double getDistance(double[] v) throws IllegalArgumentException {
 
457
        checkVectorDimensions(v.length);
 
458
        double res = 0;
 
459
        for (int i = 0; i < v.length; i++) {
 
460
            double delta = entries.get(i) - v[i];
 
461
            res += delta * delta;
 
462
        }
 
463
        return Math.sqrt(res);
 
464
    }
 
465
 
 
466
    /** {@inheritDoc} */
 
467
    public double getEntry(int index) throws MatrixIndexException {
 
468
        checkIndex(index);
 
469
        return entries.get(index);
 
470
    }
 
471
 
 
472
    /**
 
473
     * Distance between two vectors.
 
474
     * <p>This method computes the distance consistent with
 
475
     * L<sub>1</sub> norm, i.e. the sum of the absolute values of
 
476
     * elements differences.</p>
 
477
     * @param v vector to which distance is requested
 
478
     * @return distance between two vectors.
 
479
     */
 
480
    public double getL1Distance(OpenMapRealVector v) {
 
481
        double max = 0;
 
482
        Iterator iter = entries.iterator();
 
483
        while (iter.hasNext()) {
 
484
            iter.advance();
 
485
            double delta = Math.abs(iter.value() - v.getEntry(iter.key()));
 
486
            max += delta;
 
487
        }
 
488
        iter = v.getEntries().iterator();
 
489
        while (iter.hasNext()) {
 
490
            iter.advance();
 
491
            int key = iter.key();
 
492
            if (!entries.containsKey(key)) {
 
493
                double delta = Math.abs(iter.value());
 
494
                max +=  Math.abs(delta);
 
495
            }
 
496
        }
 
497
        return max;
 
498
    }
 
499
 
 
500
    /** {@inheritDoc} */
 
501
    public double getL1Distance(RealVector v) throws IllegalArgumentException {
 
502
        checkVectorDimensions(v.getDimension());
 
503
        if (v instanceof OpenMapRealVector) {
 
504
            return getL1Distance((OpenMapRealVector) v);
 
505
        }
 
506
        return getL1Distance(v.getData());
 
507
    }
 
508
 
 
509
    /** {@inheritDoc} */
 
510
    public double getL1Distance(double[] v) throws IllegalArgumentException {
 
511
        checkVectorDimensions(v.length);
 
512
        double max = 0;
 
513
        for (int i = 0; i < v.length; i++) {
 
514
            double delta = Math.abs(getEntry(i) - v[i]);
 
515
            max += delta;
 
516
        }
 
517
        return max;
 
518
    }
 
519
 
 
520
    /** {@inheritDoc} */
 
521
    public double getL1Norm() {
 
522
        double res = 0;
 
523
        Iterator iter = entries.iterator();
 
524
        while (iter.hasNext()) {
 
525
            iter.advance();
 
526
            res += Math.abs(iter.value());
 
527
        }
 
528
        return res;
 
529
    }
 
530
 
 
531
    /**
 
532
     * Optimized method to compute LInfDistance.
 
533
     * @param v The vector to compute from
 
534
     * @return the LInfDistance
 
535
     */
 
536
    private double getLInfDistance(OpenMapRealVector v) {
 
537
        double max = 0;
 
538
        Iterator iter = entries.iterator();
 
539
        while (iter.hasNext()) {
 
540
            iter.advance();
 
541
            double delta = Math.abs(iter.value() - v.getEntry(iter.key()));
 
542
            if (delta > max) {
 
543
                max = delta;
 
544
            }
 
545
        }
 
546
        iter = v.getEntries().iterator();
 
547
        while (iter.hasNext()) {
 
548
            iter.advance();
 
549
            int key = iter.key();
 
550
            if (!entries.containsKey(key)) {
 
551
                if (iter.value() > max) {
 
552
                    max = iter.value();
 
553
                }
 
554
            }
 
555
        }
 
556
        return max;
 
557
    }
 
558
 
 
559
    /** {@inheritDoc} */
 
560
    public double getLInfDistance(RealVector v) throws IllegalArgumentException {
 
561
        checkVectorDimensions(v.getDimension());
 
562
        if (v instanceof OpenMapRealVector) {
 
563
            return getLInfDistance((OpenMapRealVector) v);
 
564
        }
 
565
        return getLInfDistance(v.getData());
 
566
    }
 
567
 
 
568
    /** {@inheritDoc} */
 
569
    public double getLInfDistance(double[] v) throws IllegalArgumentException {
 
570
        checkVectorDimensions(v.length);
 
571
        double max = 0;
 
572
        for (int i = 0; i < v.length; i++) {
 
573
            double delta = Math.abs(getEntry(i) - v[i]);
 
574
            if (delta > max) {
 
575
                max = delta;
 
576
            }
 
577
        }
 
578
        return max;
 
579
    }
 
580
 
 
581
    /** {@inheritDoc} */
 
582
    public double getLInfNorm() {
 
583
        double max = 0;
 
584
        Iterator iter = entries.iterator();
 
585
        while (iter.hasNext()) {
 
586
            iter.advance();
 
587
            max += iter.value();
 
588
        }
 
589
        return max;
 
590
    }
 
591
 
 
592
    /** {@inheritDoc} */
 
593
    public double getNorm() {
 
594
        double res = 0;
 
595
        Iterator iter = entries.iterator();
 
596
        while (iter.hasNext()) {
 
597
            iter.advance();
 
598
            res += iter.value() * iter.value();
 
599
        }
 
600
        return Math.sqrt(res);
 
601
    }
 
602
 
 
603
    /** {@inheritDoc} */
 
604
    public boolean isInfinite() {
 
605
        boolean infiniteFound = false;
 
606
        Iterator iter = entries.iterator();
 
607
        while (iter.hasNext()) {
 
608
            iter.advance();
 
609
            final double value = iter.value();
 
610
            if (Double.isNaN(value)) {
 
611
                return false;
 
612
            }
 
613
            if (Double.isInfinite(value)) {
 
614
                infiniteFound = true;
 
615
            }
 
616
        }
 
617
        return infiniteFound;
 
618
    }
 
619
 
 
620
    /** {@inheritDoc} */
 
621
    public boolean isNaN() {
 
622
        Iterator iter = entries.iterator();
 
623
        while (iter.hasNext()) {
 
624
            iter.advance();
 
625
            if (Double.isNaN(iter.value())) {
 
626
                return true;
 
627
            }
 
628
        }
 
629
        return false;
 
630
    }
 
631
 
 
632
    /** {@inheritDoc} */
 
633
    public OpenMapRealVector mapAbs() {
 
634
        return copy().mapAbsToSelf();
 
635
    }
 
636
 
 
637
    /** {@inheritDoc} */
 
638
    public OpenMapRealVector mapAbsToSelf() {
 
639
        Iterator iter = entries.iterator();
 
640
        while (iter.hasNext()) {
 
641
            iter.advance();
 
642
            entries.put(iter.key(), Math.abs(iter.value()));
 
643
        }
 
644
        return this;
 
645
    }
 
646
 
 
647
    /** {@inheritDoc} */
 
648
    public OpenMapRealVector mapAcos() {
 
649
        return copy().mapAcosToSelf();
 
650
    }
 
651
 
 
652
    /** {@inheritDoc} */
 
653
    public OpenMapRealVector mapAcosToSelf() {
 
654
        for (int i = 0; i < virtualSize; i++) {
 
655
            setEntry(i, Math.acos(getEntry(i)));
 
656
        }
 
657
        return this;
 
658
    }
 
659
 
 
660
    /** {@inheritDoc} */
 
661
    public OpenMapRealVector mapAdd(double d) {
 
662
        return copy().mapAddToSelf(d);
 
663
    }
 
664
 
 
665
    /** {@inheritDoc} */
 
666
    public OpenMapRealVector mapAddToSelf(double d) {
 
667
        for (int i = 0; i < virtualSize; i++) {
 
668
            setEntry(i, getEntry(i) + d);
 
669
        }
 
670
        return this;
 
671
    }
 
672
 
 
673
    /** {@inheritDoc} */
 
674
    public OpenMapRealVector mapAsin() {
 
675
        return copy().mapAsinToSelf();
 
676
    }
 
677
 
 
678
    /** {@inheritDoc} */
 
679
    public OpenMapRealVector mapAsinToSelf() {
 
680
        Iterator iter = entries.iterator();
 
681
        while (iter.hasNext()) {
 
682
            iter.advance();
 
683
            entries.put(iter.key(), Math.asin(iter.value()));
 
684
        }
 
685
        return this;
 
686
    }
 
687
 
 
688
    /** {@inheritDoc} */
 
689
    public OpenMapRealVector mapAtan() {
 
690
        return copy().mapAtanToSelf();
 
691
    }
 
692
 
 
693
    /** {@inheritDoc} */
 
694
    public OpenMapRealVector mapAtanToSelf() {
 
695
        Iterator iter = entries.iterator();
 
696
        while (iter.hasNext()) {
 
697
            iter.advance();
 
698
            entries.put(iter.key(), Math.atan(iter.value()));
 
699
        }
 
700
        return this;
 
701
    }
 
702
 
 
703
    /** {@inheritDoc} */
 
704
    public OpenMapRealVector mapCbrt() {
 
705
        return copy().mapCbrtToSelf();
 
706
    }
 
707
 
 
708
    /** {@inheritDoc} */
 
709
    public OpenMapRealVector mapCbrtToSelf() {
 
710
        Iterator iter = entries.iterator();
 
711
        while (iter.hasNext()) {
 
712
            iter.advance();
 
713
            entries.put(iter.key(), Math.cbrt(iter.value()));
 
714
        }
 
715
        return this;
 
716
    }
 
717
 
 
718
    /** {@inheritDoc} */
 
719
    public OpenMapRealVector mapCeil() {
 
720
        return copy().mapCeilToSelf();
 
721
    }
 
722
 
 
723
    /** {@inheritDoc} */
 
724
    public OpenMapRealVector mapCeilToSelf() {
 
725
        Iterator iter = entries.iterator();
 
726
        while (iter.hasNext()) {
 
727
            iter.advance();
 
728
            entries.put(iter.key(), Math.ceil(iter.value()));
 
729
        }
 
730
        return this;
 
731
    }
 
732
 
 
733
    /** {@inheritDoc} */
 
734
    public OpenMapRealVector mapCos() {
 
735
        return copy().mapCosToSelf();
 
736
    }
 
737
 
 
738
    /** {@inheritDoc} */
 
739
    public OpenMapRealVector mapCosToSelf() {
 
740
        for (int i = 0; i < virtualSize; i++) {
 
741
            setEntry(i, Math.cos(getEntry(i)));
 
742
        }
 
743
        return this;
 
744
    }
 
745
 
 
746
    /** {@inheritDoc} */
 
747
    public OpenMapRealVector mapCosh() {
 
748
        return copy().mapCoshToSelf();
 
749
    }
 
750
 
 
751
    /** {@inheritDoc} */
 
752
    public OpenMapRealVector mapCoshToSelf() {
 
753
        for (int i = 0; i < virtualSize; i++) {
 
754
            setEntry(i, Math.cosh(getEntry(i)));
 
755
        }
 
756
        return this;
 
757
    }
 
758
 
 
759
    /** {@inheritDoc} */
 
760
    public OpenMapRealVector mapDivide(double d) {
 
761
        return copy().mapDivideToSelf(d);
 
762
    }
 
763
 
 
764
    /** {@inheritDoc} */
 
765
    public OpenMapRealVector mapDivideToSelf(double d) {
 
766
        Iterator iter = entries.iterator();
 
767
        while (iter.hasNext()) {
 
768
            iter.advance();
 
769
            entries.put(iter.key(), iter.value() / d);
 
770
        }
 
771
        return this;
 
772
    }
 
773
 
 
774
    /** {@inheritDoc} */
 
775
    public OpenMapRealVector mapExp() {
 
776
        return copy().mapExpToSelf();
 
777
    }
 
778
 
 
779
    /** {@inheritDoc} */
 
780
    public OpenMapRealVector mapExpToSelf() {
 
781
        for (int i = 0; i < virtualSize; i++) {
 
782
            entries.put(i, Math.exp(entries.get(i)));
 
783
        }
 
784
        return this;
 
785
    }
 
786
 
 
787
    /** {@inheritDoc} */
 
788
    public OpenMapRealVector mapExpm1() {
 
789
        return copy().mapExpm1ToSelf();
 
790
    }
 
791
 
 
792
    /** {@inheritDoc} */
 
793
    public OpenMapRealVector mapExpm1ToSelf() {
 
794
        Iterator iter = entries.iterator();
 
795
        while (iter.hasNext()) {
 
796
            iter.advance();
 
797
            entries.put(iter.key(), Math.expm1(iter.value()));
 
798
        }
 
799
        return this;
 
800
    }
 
801
 
 
802
    /** {@inheritDoc} */
 
803
    public OpenMapRealVector mapFloor() {
 
804
        return copy().mapFloorToSelf();
 
805
    }
 
806
 
 
807
    /** {@inheritDoc} */
 
808
    public OpenMapRealVector mapFloorToSelf() {
 
809
        Iterator iter = entries.iterator();
 
810
        while (iter.hasNext()) {
 
811
            iter.advance();
 
812
            entries.put(iter.key(), Math.floor(iter.value()));
 
813
        }
 
814
        return this;
 
815
    }
 
816
 
 
817
    /** {@inheritDoc} */
 
818
    public OpenMapRealVector mapInv() {
 
819
        return copy().mapInvToSelf();
 
820
    }
 
821
 
 
822
    /** {@inheritDoc} */
 
823
    public OpenMapRealVector mapInvToSelf() {
 
824
        for (int i = 0; i < virtualSize; i++) {
 
825
            setEntry(i, 1.0/getEntry(i));
 
826
        }
 
827
        return this;
 
828
    }
 
829
 
 
830
    /** {@inheritDoc} */
 
831
    public OpenMapRealVector mapLog() {
 
832
        return copy().mapLogToSelf();
 
833
    }
 
834
 
 
835
    /** {@inheritDoc} */
 
836
    public OpenMapRealVector mapLog10() {
 
837
        return copy().mapLog10ToSelf();
 
838
    }
 
839
 
 
840
    /** {@inheritDoc} */
 
841
    public OpenMapRealVector mapLog10ToSelf() {
 
842
        for (int i = 0; i < virtualSize; i++) {
 
843
            setEntry(i, Math.log10(getEntry(i)));
 
844
        }
 
845
        return this;
 
846
    }
 
847
 
 
848
    /** {@inheritDoc} */
 
849
    public OpenMapRealVector mapLog1p() {
 
850
        return copy().mapLog1pToSelf();
 
851
    }
 
852
 
 
853
    /** {@inheritDoc} */
 
854
    public OpenMapRealVector mapLog1pToSelf() {
 
855
        Iterator iter = entries.iterator();
 
856
        while (iter.hasNext()) {
 
857
            iter.advance();
 
858
            entries.put(iter.key(), Math.log1p(iter.value()));
 
859
        }
 
860
        return this;
 
861
    }
 
862
 
 
863
    /** {@inheritDoc} */
 
864
    public OpenMapRealVector mapLogToSelf() {
 
865
        for (int i = 0; i < virtualSize; i++) {
 
866
            setEntry(i, Math.log(getEntry(i)));
 
867
        }
 
868
       return this;
 
869
    }
 
870
 
 
871
    /** {@inheritDoc} */
 
872
    public OpenMapRealVector mapMultiply(double d) {
 
873
        return copy().mapMultiplyToSelf(d);
 
874
    }
 
875
 
 
876
    /** {@inheritDoc} */
 
877
    public OpenMapRealVector mapMultiplyToSelf(double d) {
 
878
        Iterator iter = entries.iterator();
 
879
        while (iter.hasNext()) {
 
880
            iter.advance();
 
881
            entries.put(iter.key(), iter.value() * d);
 
882
        }
 
883
        return this;
 
884
    }
 
885
    /** {@inheritDoc} */
 
886
    public OpenMapRealVector mapPow(double d) {
 
887
        return copy().mapPowToSelf(d);
 
888
    }
 
889
 
 
890
    /** {@inheritDoc} */
 
891
    public OpenMapRealVector mapPowToSelf(double d) {
 
892
        Iterator iter = entries.iterator();
 
893
        while (iter.hasNext()) {
 
894
            iter.advance();
 
895
            entries.put(iter.key(), Math.pow(iter.value(), d));
 
896
        }
 
897
        return this;
 
898
    }
 
899
 
 
900
    /** {@inheritDoc} */
 
901
    public OpenMapRealVector mapRint() {
 
902
        return copy().mapRintToSelf();
 
903
    }
 
904
 
 
905
    /** {@inheritDoc} */
 
906
    public OpenMapRealVector mapRintToSelf() {
 
907
        Iterator iter = entries.iterator();
 
908
        while (iter.hasNext()) {
 
909
            iter.advance();
 
910
            entries.put(iter.key(), Math.rint(iter.value()));
 
911
        }
 
912
        return this;
 
913
    }
 
914
 
 
915
    /** {@inheritDoc} */
 
916
    public OpenMapRealVector mapSignum() {
 
917
        return copy().mapSignumToSelf();
 
918
    }
 
919
 
 
920
    /** {@inheritDoc} */
 
921
    public OpenMapRealVector mapSignumToSelf() {
 
922
        Iterator iter = entries.iterator();
 
923
        while (iter.hasNext()) {
 
924
            iter.advance();
 
925
            entries.put(iter.key(), Math.signum(iter.value()));
 
926
        }
 
927
        return this;
 
928
    }
 
929
 
 
930
    /** {@inheritDoc} */
 
931
    public OpenMapRealVector mapSin() {
 
932
        return copy().mapSinToSelf();
 
933
    }
 
934
 
 
935
    /** {@inheritDoc} */
 
936
    public OpenMapRealVector mapSinToSelf() {
 
937
        Iterator iter = entries.iterator();
 
938
        while (iter.hasNext()) {
 
939
            iter.advance();
 
940
            entries.put(iter.key(), Math.sin(iter.value()));
 
941
        }
 
942
        return this;
 
943
    }
 
944
 
 
945
    /** {@inheritDoc} */
 
946
    public OpenMapRealVector mapSinh() {
 
947
        return copy().mapSinhToSelf();
 
948
    }
 
949
 
 
950
    /** {@inheritDoc} */
 
951
    public OpenMapRealVector mapSinhToSelf() {
 
952
 
 
953
        Iterator iter = entries.iterator();
 
954
        while (iter.hasNext()) {
 
955
            iter.advance();
 
956
            entries.put(iter.key(), Math.sinh(iter.value()));
 
957
        }
 
958
        return this;
 
959
    }
 
960
 
 
961
    /** {@inheritDoc} */
 
962
    public OpenMapRealVector mapSqrt() {
 
963
        return copy().mapSqrtToSelf();
 
964
    }
 
965
 
 
966
    /** {@inheritDoc} */
 
967
    public OpenMapRealVector mapSqrtToSelf() {
 
968
        Iterator iter = entries.iterator();
 
969
        while (iter.hasNext()) {
 
970
            iter.advance();
 
971
            entries.put(iter.key(), Math.sqrt(iter.value()));
 
972
        }
 
973
        return this;
 
974
    }
 
975
 
 
976
    /** {@inheritDoc} */
 
977
    public OpenMapRealVector mapSubtract(double d) {
 
978
        return copy().mapSubtractToSelf(d);
 
979
    }
 
980
 
 
981
    /** {@inheritDoc} */
 
982
    public OpenMapRealVector mapSubtractToSelf(double d) {
 
983
        return mapAddToSelf(-d);
 
984
    }
 
985
 
 
986
    /** {@inheritDoc} */
 
987
    public OpenMapRealVector mapTan() {
 
988
        return copy().mapTanToSelf();
 
989
    }
 
990
 
 
991
    /** {@inheritDoc} */
 
992
    public OpenMapRealVector mapTanToSelf() {
 
993
        Iterator iter = entries.iterator();
 
994
        while (iter.hasNext()) {
 
995
            iter.advance();
 
996
            entries.put(iter.key(), Math.tan(iter.value()));
 
997
        }
 
998
        return this;
 
999
    }
 
1000
 
 
1001
    /** {@inheritDoc} */
 
1002
    public OpenMapRealVector mapTanh() {
 
1003
        return copy().mapTanhToSelf();
 
1004
    }
 
1005
 
 
1006
    /** {@inheritDoc} */
 
1007
    public OpenMapRealVector mapTanhToSelf() {
 
1008
        Iterator iter = entries.iterator();
 
1009
        while (iter.hasNext()) {
 
1010
            iter.advance();
 
1011
            entries.put(iter.key(), Math.tanh(iter.value()));
 
1012
        }
 
1013
        return this;
 
1014
    }
 
1015
 
 
1016
    /** {@inheritDoc} */
 
1017
    public OpenMapRealVector mapUlp() {
 
1018
        return copy().mapUlpToSelf();
 
1019
    }
 
1020
 
 
1021
    /** {@inheritDoc} */
 
1022
    public OpenMapRealVector mapUlpToSelf() {
 
1023
        Iterator iter = entries.iterator();
 
1024
        while (iter.hasNext()) {
 
1025
            iter.advance();
 
1026
            entries.put(iter.key(), Math.ulp(iter.value()));
 
1027
        }
 
1028
        return this;
 
1029
    }
 
1030
 
 
1031
    /**
 
1032
     * Optimized method to compute the outer product.
 
1033
     * @param v The vector to comput the outer product on
 
1034
     * @return The outer product of <code>this</code> and <code>v</code>
 
1035
     * @throws IllegalArgumentException If the dimensions don't match
 
1036
     */
 
1037
    public OpenMapRealMatrix outerproduct(OpenMapRealVector v) throws IllegalArgumentException{
 
1038
        checkVectorDimensions(v.getDimension());
 
1039
        OpenMapRealMatrix res = new OpenMapRealMatrix(virtualSize, virtualSize);
 
1040
        Iterator iter = entries.iterator();
 
1041
        while (iter.hasNext()) {
 
1042
            iter.advance();
 
1043
            Iterator iter2 = v.getEntries().iterator();
 
1044
            while (iter2.hasNext()) {
 
1045
                iter2.advance();
 
1046
                res.setEntry(iter.key(), iter2.key(), iter.value()*iter2.value());
 
1047
            }
 
1048
        }
 
1049
        return res;
 
1050
    }
 
1051
 
 
1052
    /** {@inheritDoc} */
 
1053
    public RealMatrix outerProduct(RealVector v)
 
1054
            throws IllegalArgumentException {
 
1055
        checkVectorDimensions(v.getDimension());
 
1056
        if (v instanceof OpenMapRealVector) {
 
1057
            return outerproduct((OpenMapRealVector)v);
 
1058
        }
 
1059
        RealMatrix res = new OpenMapRealMatrix(virtualSize, virtualSize);
 
1060
        Iterator iter = entries.iterator();
 
1061
        while (iter.hasNext()) {
 
1062
            iter.advance();
 
1063
            int row = iter.key();
 
1064
            for (int col = 0; col < virtualSize; col++) {
 
1065
                res.setEntry(row, col, iter.value()*v.getEntry(col));
 
1066
            }
 
1067
        }
 
1068
        return res;
 
1069
    }
 
1070
 
 
1071
    /** {@inheritDoc} */
 
1072
    public RealMatrix outerProduct(double[] v) throws IllegalArgumentException {
 
1073
        checkVectorDimensions(v.length);
 
1074
        RealMatrix res = new OpenMapRealMatrix(virtualSize, virtualSize);
 
1075
        Iterator iter = entries.iterator();
 
1076
        while (iter.hasNext()) {
 
1077
            iter.advance();
 
1078
            int row = iter.key();
 
1079
            double value = iter.value();
 
1080
            for (int col = 0; col < virtualSize; col++) {
 
1081
                res.setEntry(row, col, value * v[col]);
 
1082
            }
 
1083
        }
 
1084
        return res;
 
1085
    }
 
1086
 
 
1087
    /** {@inheritDoc} */
 
1088
    public RealVector projection(RealVector v) throws IllegalArgumentException {
 
1089
        checkVectorDimensions(v.getDimension());
 
1090
        return v.mapMultiply(dotProduct(v) / v.dotProduct(v));
 
1091
    }
 
1092
 
 
1093
    /** {@inheritDoc} */
 
1094
    public OpenMapRealVector projection(double[] v) throws IllegalArgumentException {
 
1095
        checkVectorDimensions(v.length);
 
1096
        return (OpenMapRealVector) projection(new OpenMapRealVector(v));
 
1097
    }
 
1098
 
 
1099
    /** {@inheritDoc} */
 
1100
    public void setEntry(int index, double value) throws MatrixIndexException {
 
1101
        checkIndex(index);
 
1102
        if (!isZero(value)) {
 
1103
            entries.put(index, value);
 
1104
        } else if (entries.containsKey(index)) {
 
1105
            entries.remove(index);
 
1106
        }
 
1107
    }
 
1108
 
 
1109
    /** {@inheritDoc} */
 
1110
    public void setSubVector(int index, RealVector v) throws MatrixIndexException {
 
1111
        checkIndex(index);
 
1112
        checkIndex(index + v.getDimension() - 1);
 
1113
        setSubVector(index, v.getData());
 
1114
    }
 
1115
 
 
1116
    /** {@inheritDoc} */
 
1117
    public void setSubVector(int index, double[] v) throws MatrixIndexException {
 
1118
        checkIndex(index);
 
1119
        checkIndex(index + v.length - 1);
 
1120
        for (int i = 0; i < v.length; i++) {
 
1121
            setEntry(i + index, v[i]);
 
1122
        }
 
1123
    }
 
1124
 
 
1125
    /** {@inheritDoc} */
 
1126
    public void set(double value) {
 
1127
        for (int i = 0; i < virtualSize; i++) {
 
1128
            setEntry(i, value);
 
1129
        }
 
1130
    }
 
1131
 
 
1132
    /**
 
1133
     * Optimized method to subtract OpenMapRealVectors.
 
1134
     * @param v The vector to subtract from <code>this</code>
 
1135
     * @return The difference of <code>this</code> and <code>v</code>
 
1136
     * @throws IllegalArgumentException If the dimensions don't match
 
1137
     */
 
1138
    public OpenMapRealVector subtract(OpenMapRealVector v) throws IllegalArgumentException{
 
1139
        checkVectorDimensions(v.getDimension());
 
1140
        OpenMapRealVector res = copy();
 
1141
        Iterator iter = v.getEntries().iterator();
 
1142
        while (iter.hasNext()) {
 
1143
            iter.advance();
 
1144
            int key = iter.key();
 
1145
            if (entries.containsKey(key)) {
 
1146
                res.setEntry(key, entries.get(key) - iter.value());
 
1147
            } else {
 
1148
                res.setEntry(key, -iter.value());
 
1149
            }
 
1150
        }
 
1151
        return res;
 
1152
    }
 
1153
 
 
1154
    /** {@inheritDoc} */
 
1155
    public OpenMapRealVector subtract(RealVector v) throws IllegalArgumentException {
 
1156
        checkVectorDimensions(v.getDimension());
 
1157
        if (v instanceof OpenMapRealVector) {
 
1158
            return subtract((OpenMapRealVector) v);
 
1159
        }
 
1160
        return subtract(v.getData());
 
1161
    }
 
1162
 
 
1163
    /** {@inheritDoc} */
 
1164
    public OpenMapRealVector subtract(double[] v) throws IllegalArgumentException {
 
1165
        checkVectorDimensions(v.length);
 
1166
        OpenMapRealVector res = new OpenMapRealVector(this);
 
1167
        for (int i = 0; i < v.length; i++) {
 
1168
            if (entries.containsKey(i)) {
 
1169
                res.setEntry(i, entries.get(i) - v[i]);
 
1170
            } else {
 
1171
                res.setEntry(i, -v[i]);
 
1172
            }
 
1173
        }
 
1174
        return res;
 
1175
    }
 
1176
 
 
1177
 
 
1178
    /** {@inheritDoc} */
 
1179
    public OpenMapRealVector unitVector() {
 
1180
        OpenMapRealVector res = copy();
 
1181
        res.unitize();
 
1182
        return res;
 
1183
    }
 
1184
 
 
1185
    /** {@inheritDoc} */
 
1186
    public void unitize() {
 
1187
        double norm = getNorm();
 
1188
        if (isZero(norm)) {
 
1189
            throw  MathRuntimeException.createArithmeticException("cannot normalize a zero norm vector");
 
1190
        }
 
1191
        Iterator iter = entries.iterator();
 
1192
        while (iter.hasNext()) {
 
1193
            iter.advance();
 
1194
            entries.put(iter.key(), iter.value() / norm);
 
1195
        }
 
1196
 
 
1197
    }
 
1198
 
 
1199
    /**
 
1200
     * Check if an index is valid.
 
1201
     *
 
1202
     * @param index
 
1203
     *            index to check
 
1204
     * @exception MatrixIndexException
 
1205
     *                if index is not valid
 
1206
     */
 
1207
    private void checkIndex(final int index) throws MatrixIndexException {
 
1208
        if (index < 0 || index >= getDimension()) {
 
1209
            throw new MatrixIndexException(
 
1210
                    "index {0} out of allowed range [{1}, {2}]",
 
1211
                    index, 0, getDimension() - 1);
 
1212
        }
 
1213
    }
 
1214
 
 
1215
    /**
 
1216
     * Check if instance dimension is equal to some expected value.
 
1217
     *
 
1218
     * @param n
 
1219
     *            expected dimension.
 
1220
     * @exception IllegalArgumentException
 
1221
     *                if the dimension is inconsistent with vector size
 
1222
     */
 
1223
    protected void checkVectorDimensions(int n) throws IllegalArgumentException {
 
1224
        if (getDimension() != n) {
 
1225
            throw MathRuntimeException.createIllegalArgumentException(
 
1226
                    "vector length mismatch: got {0} but expected {1}",
 
1227
                    getDimension(), n);
 
1228
        }
 
1229
    }
 
1230
 
 
1231
    /** {@inheritDoc} */
 
1232
    public double[] toArray() {
 
1233
        return getData();
 
1234
    }
 
1235
 
 
1236
    /** {@inheritDoc} 
 
1237
     * <p> Implementation Note: This works on exact values, and as a result
 
1238
     * it is possible for {@code a.subtract(b)} to be the zero vector, while
 
1239
     * {@code a.hashCode() != b.hashCode()}.</p>
 
1240
     */
 
1241
    @Override
 
1242
    public int hashCode() {
 
1243
        final int prime = 31;
 
1244
        int result = 1;
 
1245
        long temp;
 
1246
        temp = Double.doubleToLongBits(epsilon);
 
1247
        result = prime * result + (int) (temp ^ (temp >>> 32));
 
1248
        result = prime * result + virtualSize;
 
1249
        Iterator iter = entries.iterator();
 
1250
        while (iter.hasNext()) {
 
1251
            iter.advance();
 
1252
            temp = Double.doubleToLongBits(iter.value());
 
1253
            result = prime * result + (int) (temp ^ (temp >>32));
 
1254
        }
 
1255
        return result;
 
1256
    }
 
1257
 
 
1258
    /**  
 
1259
     * <p> Implementation Note: This performs an exact comparison, and as a result
 
1260
     * it is possible for {@code a.subtract(b}} to be the zero vector, while 
 
1261
     * {@code  a.equals(b) == false}.</p>
 
1262
     * {@inheritDoc}
 
1263
     */
 
1264
    @Override
 
1265
    public boolean equals(Object obj) {
 
1266
        if (this == obj) {
 
1267
            return true;
 
1268
        }
 
1269
        if (obj == null) {
 
1270
            return false;
 
1271
        }
 
1272
        if (!(obj instanceof OpenMapRealVector)) {
 
1273
            return false;
 
1274
        }
 
1275
        OpenMapRealVector other = (OpenMapRealVector) obj;
 
1276
        if (virtualSize != other.virtualSize) {
 
1277
            return false;
 
1278
        }
 
1279
        if (Double.doubleToLongBits(epsilon) !=
 
1280
            Double.doubleToLongBits(other.epsilon)) {
 
1281
            return false;
 
1282
        }
 
1283
        Iterator iter = entries.iterator();
 
1284
        while (iter.hasNext()) {
 
1285
            iter.advance();
 
1286
            double test = other.getEntry(iter.key());
 
1287
            if (Double.doubleToLongBits(test) != Double.doubleToLongBits(iter.value())) {
 
1288
                return false;
 
1289
            }
 
1290
        }
 
1291
        iter = other.getEntries().iterator();
 
1292
        while (iter.hasNext()) {
 
1293
            iter.advance();
 
1294
            double test = iter.value();
 
1295
            if (Double.doubleToLongBits(test) != Double.doubleToLongBits(getEntry(iter.key()))) {
 
1296
                return false;
 
1297
            }
 
1298
        }
 
1299
        return true;
 
1300
    }
 
1301
 
 
1302
    /**
 
1303
     * 
 
1304
     * @return the percentage of none zero elements as a decimal percent.
 
1305
     */
 
1306
    public double getSparcity() {
 
1307
        return (double)entries.size()/(double)getDimension();
 
1308
    }
 
1309
 
 
1310
}