View Javadoc
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    *      https://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  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.linear;
23  
24  import java.io.Serializable;
25  import java.util.Arrays;
26  import java.util.Iterator;
27  import java.util.NoSuchElementException;
28  
29  import org.hipparchus.UnitTestUtils;
30  import org.hipparchus.analysis.UnivariateFunction;
31  import org.hipparchus.analysis.function.Abs;
32  import org.hipparchus.analysis.function.Acos;
33  import org.hipparchus.analysis.function.Asin;
34  import org.hipparchus.analysis.function.Atan;
35  import org.hipparchus.analysis.function.Cbrt;
36  import org.hipparchus.analysis.function.Ceil;
37  import org.hipparchus.analysis.function.Cos;
38  import org.hipparchus.analysis.function.Cosh;
39  import org.hipparchus.analysis.function.Exp;
40  import org.hipparchus.analysis.function.Expm1;
41  import org.hipparchus.analysis.function.Floor;
42  import org.hipparchus.analysis.function.Inverse;
43  import org.hipparchus.analysis.function.Log;
44  import org.hipparchus.analysis.function.Log10;
45  import org.hipparchus.analysis.function.Log1p;
46  import org.hipparchus.analysis.function.Power;
47  import org.hipparchus.analysis.function.Rint;
48  import org.hipparchus.analysis.function.Sin;
49  import org.hipparchus.analysis.function.Sinh;
50  import org.hipparchus.analysis.function.Sqrt;
51  import org.hipparchus.analysis.function.Tan;
52  import org.hipparchus.analysis.function.Tanh;
53  import org.hipparchus.analysis.function.Ulp;
54  import org.hipparchus.exception.MathIllegalArgumentException;
55  import org.hipparchus.exception.MathRuntimeException;
56  import org.hipparchus.util.FastMath;
57  import org.junit.Assert;
58  import org.junit.Test;
59  
60  public abstract class RealVectorAbstractTest {
61  
62      protected enum BinaryOperation {
63          ADD, SUB, MUL, DIV
64      }
65  
66      /**
67       * <p>
68       * This is an attempt at covering most particular cases of combining two
69       * values. Here {@code x} is the value returned by
70       * {@link #getPreferredEntryValue()}, while {@code y} and {@code z} are two
71       * "normal" values.
72       * </p>
73       * <ol>
74       *   <li>
75       *     Addition: the following cases should be covered
76       *     <ul>
77       *       <li>{@code (2 * x) + (-x)}</li>
78       *       <li>{@code (-x) + 2 * x}</li>
79       *       <li>{@code x + y}</li>
80       *       <li>{@code y + x}</li>
81       *       <li>{@code y + z}</li>
82       *       <li>{@code y + (x - y)}</li>
83       *       <li>{@code (y - x) + x}</li>
84       *     </ul>
85       *     The values to be considered are:
86       *     {@code x, y, z, 2 * x, -x, x - y, y - x}.
87       *   </li>
88       *   <li>
89       *     Subtraction: the following cases should be covered
90       *     <ul>
91       *       <li>{@code (2 * x) - x}</li>
92       *       <li>{@code x - y}</li>
93       *       <li>{@code y - x}</li>
94       *       <li>{@code y - z}</li>
95       *       <li>{@code y - (y - x)}</li>
96       *       <li>{@code (y + x) - y}</li>
97       *     </ul>
98       *     The values to be considered are: {@code x, y, z, x + y, y - x}.
99       *   </li>
100      *   <li>
101      *     Multiplication
102      *     <ul>
103      *       <li>{@code (x * x) * (1 / x)}</li>
104      *       <li>{@code (1 / x) * (x * x)}</li>
105      *       <li>{@code x * y}</li>
106      *       <li>{@code y * x}</li>
107      *       <li>{@code y * z}</li>
108      *     </ul>
109      *     The values to be considered are: {@code x, y, z, 1 / x, x * x}.
110      *   </li>
111      *   <li>
112      *     Division
113      *     <ul>
114      *       <li>{@code (x * x) / x}</li>
115      *       <li>{@code x / y}</li>
116      *       <li>{@code y / x}</li>
117      *       <li>{@code y / z}</li>
118      *     </ul>
119      *     The values to be considered are: {@code x, y, z, x * x}.
120      *   </li>
121      * </ol>
122      * Also to be considered {@code NaN}, {@code POSITIVE_INFINITY},
123      * {@code NEGATIVE_INFINITY}, {@code +0.0}, {@code -0.0}.
124      */
125     private final double[] values;
126 
127     /**
128      * Creates a new instance of {@link RealVector}, with specified entries.
129      * The returned vector must be of the type currently tested. It should be
130      * noted that some tests assume that no references to the specified
131      * {@code double[]} are kept in the returned object: if necessary, defensive
132      * copy of this array should be made.
133      *
134      * @param data the entries of the vector to be created
135      * @return a new {@link RealVector} of the type to be tested
136      */
137     public abstract RealVector create(double[] data);
138 
139     /**
140      * Creates a new instance of {@link RealVector}, with specified entries.
141      * The type of the returned vector must be different from the type currently
142      * tested. It should be noted that some tests assume that no references to
143      * the specified {@code double[]} are kept in the returned object: if
144      * necessary, defensive copy of this array should be made.
145      *
146      * @param data the entries of the vector to be created
147      * @return a new {@link RealVector} of an alien type
148      */
149     public RealVector createAlien(double[] data){
150         return new RealVectorTestImpl(data);
151     }
152 
153     /**
154      * Returns a preferred value of the entries, to be tested specifically. Some
155      * implementations of {@link RealVector} (e.g. {@link OpenMapRealVector}) do
156      * not store specific values of entries. In order to ensure that all tests
157      * take into account this specific value, some entries of the vectors to be
158      * tested are deliberately set to the value returned by the present method.
159      * The default implementation returns {@code 0.0}.
160      *
161      * @return a value which <em>should</em> be present in all vectors to be
162      * tested
163      */
164     public double getPreferredEntryValue() {
165         return 0.0;
166     }
167 
168     public RealVectorAbstractTest() {
169         /*
170          * Make sure that x, y, z are three different values. Also, x is the
171          * preferred value (e.g. the value which is not stored in sparse
172          * implementations).
173          */
174         final double x = getPreferredEntryValue();
175         final double y = x + 1d;
176         final double z = y + 1d;
177 
178         values =
179             new double[] {
180                 Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY,
181                 0d, -0d, x, y, z, 2 * x, -x, 1 / x, x * x, x + y, x - y, y - x
182             };
183     }
184 
185     @Test
186     public void testGetDimension() {
187         final double x = getPreferredEntryValue();
188         final double[] data1 = {x, x, x, x};
189         Assert.assertEquals(data1.length, create(data1).getDimension());
190         final double y = x + 1;
191         final double[] data2 = {y, y, y, y};
192         Assert.assertEquals(data2.length, create(data2).getDimension());
193     }
194 
195     @Test
196     public void testGetEntry() {
197         final double x = getPreferredEntryValue();
198         final double[] data = {x, 1d, 2d, x, x};
199         final RealVector v = create(data);
200         for (int i = 0; i < data.length; i++) {
201             Assert.assertEquals("entry " + i, data[i], v.getEntry(i), 0d);
202         }
203     }
204 
205     @Test(expected=MathIllegalArgumentException.class)
206     public void testGetEntryInvalidIndex1() {
207         create(new double[4]).getEntry(-1);
208     }
209 
210     @Test(expected=MathIllegalArgumentException.class)
211     public void testGetEntryInvalidIndex2() {
212         create(new double[4]).getEntry(4);
213     }
214 
215     @Test
216     public void testSetEntry() {
217         final double x = getPreferredEntryValue();
218         final double[] data = {x, 1d, 2d, x, x};
219         final double[] expected = data.clone();
220         final RealVector actual = create(data);
221 
222         /*
223          * Try setting to any value.
224          */
225         for (int i = 0; i < data.length; i++) {
226             final double oldValue = data[i];
227             final double newValue = oldValue + 1d;
228             expected[i] = newValue;
229             actual.setEntry(i, newValue);
230             UnitTestUtils.assertEquals("while setting entry #" + i, expected,
231                 actual, 0d);
232             expected[i] = oldValue;
233             actual.setEntry(i, oldValue);
234         }
235 
236         /*
237          * Try setting to the preferred value.
238          */
239         for (int i = 0; i < data.length; i++) {
240             final double oldValue = data[i];
241             final double newValue = x;
242             expected[i] = newValue;
243             actual.setEntry(i, newValue);
244             UnitTestUtils.assertEquals("while setting entry #" + i, expected,
245                 actual, 0d);
246             expected[i] = oldValue;
247             actual.setEntry(i, oldValue);
248         }
249     }
250 
251     @Test(expected=MathIllegalArgumentException.class)
252     public void testSetEntryInvalidIndex1() {
253         create(new double[4]).setEntry(-1, getPreferredEntryValue());
254     }
255 
256     @Test(expected=MathIllegalArgumentException.class)
257     public void testSetEntryInvalidIndex2() {
258         create(new double[4]).setEntry(4, getPreferredEntryValue());
259     }
260 
261     @Test
262     public void testAddToEntry() {
263         final double x = getPreferredEntryValue();
264         final double[] data1 = {x, 1d, 2d, x, x};
265 
266         final double[] expected = data1.clone();
267         final RealVector actual = create(data1);
268 
269         /*
270          * Try adding any value.
271          */
272         double increment = 1d;
273         for (int i = 0; i < data1.length; i++) {
274             final double oldValue = data1[i];
275             expected[i] += increment;
276             actual.addToEntry(i, increment);
277             UnitTestUtils.assertEquals("while incrementing entry #" + i, expected,
278                 actual, 0d);
279             expected[i] = oldValue;
280             actual.setEntry(i, oldValue);
281         }
282 
283         /*
284          * Try incrementing so that result is equal to preferred value.
285          */
286         for (int i = 0; i < data1.length; i++) {
287             final double oldValue = data1[i];
288             increment = x - oldValue;
289             expected[i] = x;
290             actual.addToEntry(i, increment);
291             UnitTestUtils.assertEquals("while incrementing entry #" + i, expected,
292                 actual, 0d);
293             expected[i] = oldValue;
294             actual.setEntry(i, oldValue);
295         }
296     }
297 
298     @Test(expected=MathIllegalArgumentException.class)
299     public void testAddToEntryInvalidIndex1() {
300         create(new double[3]).addToEntry(-1, getPreferredEntryValue());
301     }
302 
303     @Test(expected=MathIllegalArgumentException.class)
304     public void testAddToEntryInvalidIndex2() {
305         create(new double[3]).addToEntry(4, getPreferredEntryValue());
306     }
307 
308     private void doTestAppendVector(final String message, final RealVector v1,
309         final RealVector v2, final double delta) {
310 
311         final int n1 = v1.getDimension();
312         final int n2 = v2.getDimension();
313         final RealVector v = v1.append(v2);
314         Assert.assertEquals(message, n1 + n2, v.getDimension());
315         for (int i = 0; i < n1; i++) {
316             final String msg = message + ", entry #" + i;
317             Assert.assertEquals(msg, v1.getEntry(i), v.getEntry(i), delta);
318         }
319         for (int i = 0; i < n2; i++) {
320             final String msg = message + ", entry #" + (n1 + i);
321             Assert.assertEquals(msg, v2.getEntry(i), v.getEntry(n1 + i), delta);
322         }
323     }
324 
325     @Test
326     public void testAppendVector() {
327         final double x = getPreferredEntryValue();
328         final double[] data1 =  {x, 1d, 2d, x, x};
329         final double[] data2 =  {x, x, 3d, x, 4d, x};
330 
331         doTestAppendVector("same type", create(data1), create(data2), 0d);
332         doTestAppendVector("mixed types", create(data1), createAlien(data2), 0d);
333     }
334 
335     private void doTestAppendScalar(final String message, final RealVector v,
336         final double d, final double delta) {
337 
338         final int n = v.getDimension();
339         final RealVector w = v.append(d);
340         Assert.assertEquals(message, n + 1, w.getDimension());
341         for (int i = 0; i < n; i++) {
342             final String msg = message + ", entry #" + i;
343             Assert.assertEquals(msg, v.getEntry(i), w.getEntry(i), delta);
344         }
345         final String msg = message + ", entry #" + n;
346         Assert.assertEquals(msg, d, w.getEntry(n), delta);
347     }
348 
349     @Test
350     public void testAppendScalar() {
351         final double x = getPreferredEntryValue();
352         final double[] data = new double[] {x, 1d, 2d, x, x};
353 
354         doTestAppendScalar("", create(data), 1d, 0d);
355         doTestAppendScalar("", create(data), x, 0d);
356     }
357 
358     @Test
359     public void testGetSubVector() {
360         final double x = getPreferredEntryValue();
361         final double[] data = {x, x, x, 1d, x, 2d, x, x, 3d, x, x, x, 4d, x, x, x};
362         final int index = 1;
363         final int n = data.length - 5;
364         final RealVector actual = create(data).getSubVector(index, n);
365         final double[] expected = new double[n];
366         System.arraycopy(data, index, expected, 0, n);
367         UnitTestUtils.assertEquals("", expected, actual, 0d);
368     }
369 
370     @Test(expected = MathIllegalArgumentException.class)
371     public void testGetSubVectorInvalidIndex1() {
372         final int n = 10;
373         create(new double[n]).getSubVector(-1, 2);
374     }
375 
376     @Test(expected = MathIllegalArgumentException.class)
377     public void testGetSubVectorInvalidIndex2() {
378         final int n = 10;
379         create(new double[n]).getSubVector(n, 2);
380     }
381 
382     @Test(expected = MathIllegalArgumentException.class)
383     public void testGetSubVectorInvalidIndex3() {
384         final int n = 10;
385         create(new double[n]).getSubVector(0, n + 1);
386     }
387 
388     @Test(expected = MathIllegalArgumentException.class)
389     public void testGetSubVectorInvalidIndex4() {
390         final int n = 10;
391         create(new double[n]).getSubVector(3, -2);
392     }
393 
394     @Test
395     public void testSetSubVectorSameType() {
396         final double x = getPreferredEntryValue();
397         final double[] expected = {x, x, x, 1d, x, 2d, x, x, 3d, x, x, x, 4d, x, x, x};
398         final double[] sub = {5d, x, 6d, 7d, 8d};
399         final RealVector actual = create(expected);
400         final int index = 2;
401         actual.setSubVector(index, create(sub));
402 
403         for (int i = 0; i < sub.length; i++){
404             expected[index + i] = sub[i];
405         }
406         UnitTestUtils.assertEquals("", expected, actual, 0d);
407     }
408 
409     @Test
410     public void testSetSubVectorMixedType() {
411         final double x = getPreferredEntryValue();
412         final double[] expected = {x, x, x, 1d, x, 2d, x, x, 3d, x, x, x, 4d, x, x, x};
413         final double[] sub = {5d, x, 6d, 7d, 8d};
414         final RealVector actual = create(expected);
415         final int index = 2;
416         actual.setSubVector(index, createAlien(sub));
417 
418         for (int i = 0; i < sub.length; i++){
419             expected[index + i] = sub[i];
420         }
421         UnitTestUtils.assertEquals("", expected, actual, 0d);
422     }
423 
424     @Test(expected = MathIllegalArgumentException.class)
425     public void testSetSubVectorInvalidIndex1() {
426         create(new double[10]).setSubVector(-1, create(new double[2]));
427     }
428 
429     @Test(expected = MathIllegalArgumentException.class)
430     public void testSetSubVectorInvalidIndex2() {
431         create(new double[10]).setSubVector(10, create(new double[2]));
432     }
433 
434     @Test(expected = MathIllegalArgumentException.class)
435     public void testSetSubVectorInvalidIndex3() {
436         create(new double[10]).setSubVector(9, create(new double[2]));
437     }
438 
439     @Test
440     public void testIsNaN() {
441         final RealVector v = create(new double[] {0, 1, 2});
442 
443         Assert.assertFalse(v.isNaN());
444         v.setEntry(1, Double.NaN);
445         Assert.assertTrue(v.isNaN());
446     }
447 
448     @Test
449     public void testIsInfinite() {
450         final RealVector v = create(new double[] { 0, 1, 2 });
451 
452         Assert.assertFalse(v.isInfinite());
453         v.setEntry(0, Double.POSITIVE_INFINITY);
454         Assert.assertTrue(v.isInfinite());
455         v.setEntry(1, Double.NaN);
456         Assert.assertFalse(v.isInfinite());
457     }
458 
459     protected void doTestEbeBinaryOperation(final BinaryOperation op, final boolean mixed, boolean ignoreSpecial) {
460         final double[] data1 = new double[values.length * values.length];
461         final double[] data2 = new double[values.length * values.length];
462         int k = 0;
463         for (int i = 0; i < values.length; i++) {
464             for (int j = 0; j < values.length; j++) {
465                 data1[k] = values[i];
466                 data2[k] = values[j];
467                 ++k;
468             }
469         }
470         final RealVector v1 = create(data1);
471         final RealVector v2 = mixed ? createAlien(data2) : create(data2);
472         final RealVector actual;
473         switch (op) {
474             case ADD:
475                 actual = v1.add(v2);
476                 break;
477             case SUB:
478                 actual = v1.subtract(v2);
479                 break;
480             case MUL:
481                 actual = v1.ebeMultiply(v2);
482                 break;
483             case DIV:
484                 actual = v1.ebeDivide(v2);
485                 break;
486             default:
487                 throw new AssertionError("unexpected value");
488         }
489         final double[] expected = new double[data1.length];
490         for (int i = 0; i < expected.length; i++) {
491             switch (op) {
492                 case ADD:
493                     expected[i] = data1[i] + data2[i];
494                     break;
495                 case SUB:
496                     expected[i] = data1[i] - data2[i];
497                     break;
498                 case MUL:
499                     expected[i] = data1[i] * data2[i];
500                     break;
501                 case DIV:
502                     expected[i] = data1[i] / data2[i];
503                     break;
504                 default:
505                     throw new AssertionError("unexpected value");
506             }
507         }
508         for (int i = 0; i < expected.length; i++) {
509             boolean isSpecial = Double.isNaN(expected[i]) || Double.isInfinite(expected[i]);
510             if (!(isSpecial && ignoreSpecial)) {
511                 final String msg = "entry #"+i+", left = "+data1[i]+", right = " + data2[i];
512                 Assert.assertEquals(msg, expected[i], actual.getEntry(i), 0.0);
513             }
514         }
515     }
516 
517     private void doTestEbeBinaryOperationDimensionMismatch(final BinaryOperation op) {
518         final int n = 10;
519         switch (op) {
520             case ADD:
521                 create(new double[n]).add(create(new double[n + 1]));
522                 break;
523             case SUB:
524                 create(new double[n]).subtract(create(new double[n + 1]));
525                 break;
526             case MUL:
527                 create(new double[n]).ebeMultiply(create(new double[n + 1]));
528                 break;
529             case DIV:
530                 create(new double[n]).ebeDivide(create(new double[n + 1]));
531                 break;
532             default:
533                 throw new AssertionError("unexpected value");
534         }
535     }
536 
537     @Test
538     public void testAddSameType() {
539         doTestEbeBinaryOperation(BinaryOperation.ADD, false, false);
540     }
541 
542     @Test
543     public void testAddMixedTypes() {
544         doTestEbeBinaryOperation(BinaryOperation.ADD, true, false);
545     }
546 
547     @Test(expected = MathIllegalArgumentException.class)
548     public void testAddDimensionMismatch() {
549         doTestEbeBinaryOperationDimensionMismatch(BinaryOperation.ADD);
550     }
551 
552     @Test
553     public void testSubtractSameType() {
554         doTestEbeBinaryOperation(BinaryOperation.SUB, false, false);
555     }
556 
557     @Test
558     public void testSubtractMixedTypes() {
559         doTestEbeBinaryOperation(BinaryOperation.SUB, true, false);
560     }
561 
562     @Test(expected = MathIllegalArgumentException.class)
563     public void testSubtractDimensionMismatch() {
564         doTestEbeBinaryOperationDimensionMismatch(BinaryOperation.SUB);
565     }
566 
567     @Test
568     public void testEbeMultiplySameType() {
569         doTestEbeBinaryOperation(BinaryOperation.MUL, false, false);
570     }
571 
572     @Test
573     public void testEbeMultiplyMixedTypes() {
574         doTestEbeBinaryOperation(BinaryOperation.MUL, true, false);
575     }
576 
577     @Test(expected = MathIllegalArgumentException.class)
578     public void testEbeMultiplyDimensionMismatch() {
579         doTestEbeBinaryOperationDimensionMismatch(BinaryOperation.MUL);
580     }
581 
582     @Test
583     public void testEbeDivideSameType() {
584         doTestEbeBinaryOperation(BinaryOperation.DIV, false, false);
585     }
586 
587    @Test
588     public void testEbeDivideMixedTypes() {
589         doTestEbeBinaryOperation(BinaryOperation.DIV, true, false);
590     }
591 
592     @Test(expected = MathIllegalArgumentException.class)
593     public void testEbeDivideDimensionMismatch() {
594         doTestEbeBinaryOperationDimensionMismatch(BinaryOperation.DIV);
595     }
596 
597     private void doTestGetDistance(final boolean mixed) {
598         final double x = getPreferredEntryValue();
599         final double[] data1 = new double[] { x, x, 1d, x, 2d, x, x, 3d, x };
600         final double[] data2 = new double[] { 4d, x, x, 5d, 6d, 7d, x, x, 8d };
601         final RealVector v1 = create(data1);
602         final RealVector v2;
603         if (mixed) {
604             v2 = createAlien(data2);
605         } else {
606             v2 = create(data2);
607         }
608         final double actual = v1.getDistance(v2);
609         double expected = 0d;
610         for (int i = 0; i < data1.length; i++) {
611             final double delta = data2[i] - data1[i];
612             expected += delta * delta;
613         }
614         expected = FastMath.sqrt(expected);
615         Assert.assertEquals("", expected, actual, 0d);
616     }
617 
618     @Test
619     public void testGetDistanceSameType() {
620         doTestGetDistance(false);
621     }
622 
623     @Test
624     public void testGetDistanceMixedTypes() {
625         doTestGetDistance(true);
626     }
627 
628     @Test(expected = MathIllegalArgumentException.class)
629     public void testGetDistanceDimensionMismatch() {
630         create(new double[4]).getDistance(createAlien(new double[5]));
631     }
632 
633     @Test
634     public void testGetNorm() {
635         final double x = getPreferredEntryValue();
636         final double[] data = new double[] { x, x, 1d, x, 2d, x, x, 3d, x };
637         final RealVector v = create(data);
638         final double actual = v.getNorm();
639         double expected = 0d;
640         for (int i = 0; i < data.length; i++) {
641             expected += data[i] * data[i];
642         }
643         expected = FastMath.sqrt(expected);
644         Assert.assertEquals("", expected, actual, 0d);
645     }
646 
647     private void doTestGetL1Distance(final boolean mixed) {
648         final double x = getPreferredEntryValue();
649         final double[] data1 = new double[] { x, x, 1d, x, 2d, x, x, 3d, x };
650         final double[] data2 = new double[] { 4d, x, x, 5d, 6d, 7d, x, x, 8d };
651         final RealVector v1 = create(data1);
652         final RealVector v2;
653         if (mixed) {
654             v2 = createAlien(data2);
655         } else {
656             v2 = create(data2);
657         }
658         final double actual = v1.getL1Distance(v2);
659         double expected = 0d;
660         for (int i = 0; i < data1.length; i++) {
661             final double delta = data2[i] - data1[i];
662             expected += FastMath.abs(delta);
663         }
664         Assert.assertEquals("", expected, actual, 0d);
665     }
666 
667     @Test
668     public void testGetL1DistanceSameType() {
669         doTestGetL1Distance(false);
670     }
671 
672     @Test
673     public void testGetL1DistanceMixedTypes() {
674         doTestGetL1Distance(true);
675     }
676 
677     @Test(expected = MathIllegalArgumentException.class)
678     public void testGetL1DistanceDimensionMismatch() {
679         create(new double[4]).getL1Distance(createAlien(new double[5]));
680     }
681 
682     @Test
683     public void testGetL1Norm() {
684         final double x = getPreferredEntryValue();
685         final double[] data = new double[] { x, x, 1d, x, 2d, x, x, 3d, x };
686         final RealVector v = create(data);
687         final double actual = v.getL1Norm();
688         double expected = 0d;
689         for (int i = 0; i < data.length; i++) {
690             expected += FastMath.abs(data[i]);
691         }
692         Assert.assertEquals("", expected, actual, 0d);
693 
694     }
695 
696     private void doTestGetLInfDistance(final boolean mixed) {
697         final double x = getPreferredEntryValue();
698         final double[] data1 = new double[] { x, x, 1d, x, 2d, x, x, 3d, x };
699         final double[] data2 = new double[] { 4d, x, x, 5d, 6d, 7d, x, x, 8d };
700         final RealVector v1 = create(data1);
701         final RealVector v2;
702         if (mixed) {
703             v2 = createAlien(data2);
704         } else {
705             v2 = create(data2);
706         }
707         final double actual = v1.getLInfDistance(v2);
708         double expected = 0d;
709         for (int i = 0; i < data1.length; i++) {
710             final double delta = data2[i] - data1[i];
711             expected = FastMath.max(expected, FastMath.abs(delta));
712         }
713         Assert.assertEquals("", expected, actual, 0d);
714     }
715 
716     @Test
717     public void testGetLInfDistanceSameType() {
718         doTestGetLInfDistance(false);
719     }
720 
721     @Test
722     public void testGetLInfDistanceMixedTypes() {
723         doTestGetLInfDistance(true);
724     }
725 
726     @Test(expected = MathIllegalArgumentException.class)
727     public void testGetLInfDistanceDimensionMismatch() {
728         create(new double[4]).getLInfDistance(createAlien(new double[5]));
729     }
730 
731     @Test
732     public void testGetLInfNorm() {
733         final double x = getPreferredEntryValue();
734         final double[] data = new double[] { x, x, 1d, x, 2d, x, x, 3d, x };
735         final RealVector v = create(data);
736         final double actual = v.getLInfNorm();
737         double expected = 0d;
738         for (int i = 0; i < data.length; i++) {
739             expected = FastMath.max(expected, FastMath.abs(data[i]));
740         }
741         Assert.assertEquals("", expected, actual, 0d);
742 
743     }
744 
745     private void doTestMapBinaryOperation(final BinaryOperation op, final boolean inPlace) {
746         final double[] expected = new double[values.length];
747         for (int i = 0; i < values.length; i++) {
748             final double d = values[i];
749             for (int j = 0; j < expected.length; j++) {
750                 switch (op) {
751                     case ADD:
752                         expected[j] = values[j] + d;
753                         break;
754                     case SUB:
755                         expected[j] = values[j] - d;
756                         break;
757                     case MUL:
758                         expected[j] = values[j] * d;
759                         break;
760                     case DIV:
761                         expected[j] = values[j] / d;
762                         break;
763                     default:
764                         throw new AssertionError("unexpected value");
765                 }
766             }
767             final RealVector v = create(values);
768             final RealVector actual;
769             if (inPlace) {
770                 switch (op) {
771                     case ADD:
772                         actual = v.mapAddToSelf(d);
773                         break;
774                     case SUB:
775                         actual = v.mapSubtractToSelf(d);
776                         break;
777                     case MUL:
778                         actual = v.mapMultiplyToSelf(d);
779                         break;
780                     case DIV:
781                         actual = v.mapDivideToSelf(d);
782                         break;
783                     default:
784                         throw new AssertionError("unexpected value");
785                 }
786             } else {
787                 switch (op) {
788                     case ADD:
789                         actual = v.mapAdd(d);
790                         break;
791                     case SUB:
792                         actual = v.mapSubtract(d);
793                         break;
794                     case MUL:
795                         actual = v.mapMultiply(d);
796                         break;
797                     case DIV:
798                         actual = v.mapDivide(d);
799                         break;
800                     default:
801                         throw new AssertionError("unexpected value");
802                 }
803             }
804             UnitTestUtils.assertEquals(Double.toString(d), expected, actual, 0d);
805         }
806     }
807 
808     @Test
809     public void testMapAdd() {
810         doTestMapBinaryOperation(BinaryOperation.ADD, false);
811     }
812 
813     @Test
814     public void testMapAddToSelf() {
815         doTestMapBinaryOperation(BinaryOperation.ADD, true);
816     }
817 
818     @Test
819     public void testMapSubtract() {
820         doTestMapBinaryOperation(BinaryOperation.SUB, false);
821     }
822 
823     @Test
824     public void testMapSubtractToSelf() {
825         doTestMapBinaryOperation(BinaryOperation.SUB, true);
826     }
827 
828     @Test
829     public void testMapMultiply() {
830         doTestMapBinaryOperation(BinaryOperation.MUL, false);
831     }
832 
833     @Test
834     public void testMapMultiplyToSelf() {
835         doTestMapBinaryOperation(BinaryOperation.MUL, true);
836     }
837 
838     @Test
839     public void testMapDivide() {
840         doTestMapBinaryOperation(BinaryOperation.DIV, false);
841     }
842 
843     @Test
844     public void testMapDivideToSelf() {
845         doTestMapBinaryOperation(BinaryOperation.DIV, true);
846     }
847 
848     private void doTestMapFunction(final UnivariateFunction f,
849         final boolean inPlace) {
850         final double[] data = new double[values.length + 6];
851         System.arraycopy(values, 0, data, 0, values.length);
852         data[values.length + 0] = 0.5 * FastMath.PI;
853         data[values.length + 1] = -0.5 * FastMath.PI;
854         data[values.length + 2] = FastMath.E;
855         data[values.length + 3] = -FastMath.E;
856         data[values.length + 4] = 1.0;
857         data[values.length + 5] = -1.0;
858         final double[] expected = new double[data.length];
859         for (int i = 0; i < data.length; i++) {
860             expected[i] = f.value(data[i]);
861         }
862         final RealVector v = create(data);
863         final RealVector actual;
864         if (inPlace) {
865             actual = v.mapToSelf(f);
866             Assert.assertSame(v, actual);
867         } else {
868             actual = v.map(f);
869         }
870         UnitTestUtils.assertEquals(f.getClass().getSimpleName(), expected, actual, 1E-16);
871     }
872 
873     protected UnivariateFunction[] createFunctions() {
874         return new UnivariateFunction[] {
875             new Power(2.0), new Exp(), new Expm1(), new Log(), new Log10(),
876             new Log1p(), new Cosh(), new Sinh(), new Tanh(), new Cos(),
877             new Sin(), new Tan(), new Acos(), new Asin(), new Atan(),
878             new Inverse(), new Abs(), new Sqrt(), new Cbrt(), new Ceil(),
879             new Floor(), new Rint(), new Ulp()
880         };
881     }
882 
883     @Test
884     public void testMap() {
885         final UnivariateFunction[] functions = createFunctions();
886         for (UnivariateFunction f : functions) {
887             doTestMapFunction(f, false);
888         }
889     }
890 
891     @Test
892     public void testMapToSelf() {
893         final UnivariateFunction[] functions = createFunctions();
894         for (UnivariateFunction f : functions) {
895             doTestMapFunction(f, true);
896         }
897     }
898 
899     private void doTestOuterProduct(final boolean mixed) {
900         final double[] dataU = values;
901         final RealVector u = create(dataU);
902         final double[] dataV = new double[values.length + 3];
903         System.arraycopy(values, 0, dataV, 0, values.length);
904         dataV[values.length] = 1d;
905         dataV[values.length] = -2d;
906         dataV[values.length] = 3d;
907         final RealVector v;
908         if (mixed) {
909             v = createAlien(dataV);
910         } else {
911             v = create(dataV);
912         }
913         final RealMatrix uv = u.outerProduct(v);
914         Assert.assertEquals("number of rows", dataU.length, uv
915             .getRowDimension());
916         Assert.assertEquals("number of columns", dataV.length, uv
917             .getColumnDimension());
918         for (int i = 0; i < dataU.length; i++) {
919             for (int j = 0; j < dataV.length; j++) {
920                 final double expected = dataU[i] * dataV[j];
921                 final double actual = uv.getEntry(i, j);
922                 Assert.assertEquals(dataU[i] + " * " + dataV[j], expected, actual, 0d);
923             }
924         }
925     }
926 
927     @Test
928     public void testOuterProductSameType() {
929         doTestOuterProduct(false);
930     }
931 
932     @Test
933     public void testOuterProductMixedTypes() {
934         doTestOuterProduct(true);
935     }
936 
937     private void doTestProjection(final boolean mixed) {
938         final double x = getPreferredEntryValue();
939         final double[] data1 = {
940             x, 1d, x, x, 2d, x, x, x, 3d, x, x, x, x
941         };
942         final double[] data2 = {
943             5d, -6d, 7d, x, x, -8d, -9d, 10d, 11d, x, 12d, 13d, -15d
944         };
945         double dotProduct = 0d;
946         double norm2 = 0d;
947         for (int i = 0; i < data1.length; i++){
948             dotProduct += data1[i] * data2[i];
949             norm2 += data2[i] * data2[i];
950         }
951         final double s = dotProduct / norm2;
952         final double[] expected = new double[data1.length];
953         for (int i = 0; i < data2.length; i++) {
954             expected[i] = s * data2[i];
955         }
956         final RealVector v1 = create(data1);
957         final RealVector v2;
958         if (mixed) {
959             v2 = createAlien(data2);
960         } else {
961             v2 = create(data2);
962         }
963         final RealVector actual = v1.projection(v2);
964         UnitTestUtils.assertEquals("", expected, actual, 0d);
965     }
966 
967     @Test
968     public void testProjectionSameType() {
969         doTestProjection(false);
970     }
971 
972     @Test
973     public void testProjectionMixedTypes() {
974         doTestProjection(true);
975     }
976 
977     @Test(expected = MathRuntimeException.class)
978     public void testProjectionNullVector() {
979         create(new double[4]).projection(create(new double[4]));
980     }
981 
982     @Test(expected = MathIllegalArgumentException.class)
983     public void testProjectionDimensionMismatch() {
984         final RealVector v1 = create(new double[4]);
985         final RealVector v2 = create(new double[5]);
986         v2.set(1.0);
987         v1.projection(v2);
988     }
989 
990     @Test
991     public void testSet() {
992         for (int i = 0; i < values.length; i++) {
993             final double expected = values[i];
994             final RealVector v = create(values);
995             v.set(expected);
996             for (int j = 0; j < values.length; j++) {
997                 Assert.assertEquals("entry #" + j, expected, v.getEntry(j), 0);
998             }
999         }
1000     }
1001 
1002     @Test
1003     public void testToArray() {
1004         final double[] data = create(values).toArray();
1005         Assert.assertNotSame(values, data);
1006         for (int i = 0; i < values.length; i++) {
1007             Assert.assertEquals("entry #" + i, values[i], data[i], 0);
1008         }
1009     }
1010 
1011     private void doTestUnitVector(final boolean inPlace) {
1012         final double x = getPreferredEntryValue();
1013         final double[] data = {
1014             x, 1d, x, x, 2d, x, x, x, 3d, x, x, x, x
1015         };
1016         double norm = 0d;
1017         for (int i = 0; i < data.length; i++) {
1018             norm += data[i] * data[i];
1019         }
1020         norm = FastMath.sqrt(norm);
1021         final double[] expected = new double[data.length];
1022         for (int i = 0; i < expected.length; i++) {
1023             expected[i] = data[i] / norm;
1024         }
1025         final RealVector v = create(data);
1026         final RealVector actual;
1027         if (inPlace) {
1028             v.unitize();
1029             actual = v;
1030         } else {
1031             actual = v.unitVector();
1032             Assert.assertNotSame(v, actual);
1033         }
1034         UnitTestUtils.assertEquals("", expected, actual, 0d);
1035     }
1036 
1037     @Test
1038     public void testUnitVector() {
1039         doTestUnitVector(false);
1040     }
1041 
1042     @Test
1043     public void testUnitize() {
1044         doTestUnitVector(true);
1045     }
1046 
1047     private void doTestUnitVectorNullVector(final boolean inPlace) {
1048         final double[] data = {
1049             0d, 0d, 0d, 0d, 0d
1050         };
1051         if (inPlace) {
1052             create(data).unitize();
1053         } else {
1054             create(data).unitVector();
1055         }
1056     }
1057 
1058     @Test(expected=MathRuntimeException.class)
1059     public void testUnitVectorNullVector() {
1060         doTestUnitVectorNullVector(false);
1061     }
1062 
1063     @Test(expected=MathRuntimeException.class)
1064     public void testUnitizeNullVector() {
1065         doTestUnitVectorNullVector(true);
1066     }
1067 
1068     @Test
1069     public void testIterator() {
1070         final RealVector v = create(values);
1071         final Iterator<RealVector.Entry> it = v.iterator();
1072         for (int i = 0; i < values.length; i++) {
1073             Assert.assertTrue("entry #" + i, it.hasNext());
1074             final RealVector.Entry e = it.next();
1075             Assert.assertEquals("", i, e.getIndex());
1076             Assert.assertEquals("", values[i], e.getValue(), 0d);
1077             try {
1078                 it.remove();
1079                 Assert.fail("MathRuntimeException should have been thrown");
1080             } catch (MathRuntimeException exc) {
1081                 // Expected behavior
1082             }
1083         }
1084         Assert.assertFalse(it.hasNext());
1085         try {
1086             it.next();
1087             Assert.fail("NoSuchElementException should have been thrown");
1088         } catch (NoSuchElementException e) {
1089             // Expected behavior
1090         }
1091     }
1092 
1093     private void doTestCombine(final boolean inPlace, final boolean mixed) {
1094         final int n = values.length * values.length;
1095         final double[] data1 = new double[n];
1096         final double[] data2 = new double[n];
1097         for (int i = 0; i < values.length; i++) {
1098             for (int j = 0; j < values.length; j++) {
1099                 final int index = values.length * i + j;
1100                 data1[index] = values[i];
1101                 data2[index] = values[j];
1102             }
1103         }
1104         final RealVector v1 = create(data1);
1105         final RealVector v2 = mixed ? createAlien(data2) : create(data2);
1106         final double[] expected = new double[n];
1107         for (int i = 0; i < values.length; i++) {
1108             final double a1 = values[i];
1109             for (int j = 0; j < values.length; j++) {
1110                 final double a2 = values[j];
1111                 for (int k = 0; k < n; k++) {
1112                     expected[k] = a1 * data1[k] + a2 * data2[k];
1113                 }
1114                 final RealVector actual;
1115                 if (inPlace) {
1116                     final RealVector v1bis = v1.copy();
1117                     actual = v1bis.combineToSelf(a1, a2, v2);
1118                     Assert.assertSame(v1bis, actual);
1119                 } else {
1120                     actual = v1.combine(a1, a2, v2);
1121                 }
1122                 UnitTestUtils.assertEquals("a1 = " + a1 + ", a2 = " + a2, expected,
1123                     actual, 0.);
1124             }
1125         }
1126     }
1127 
1128     private void doTestCombineDimensionMismatch(final boolean inPlace, final boolean mixed) {
1129         final RealVector v1 = create(new double[10]);
1130         final RealVector v2;
1131         if (mixed) {
1132             v2 = createAlien(new double[15]);
1133         } else {
1134             v2 = create(new double[15]);
1135         }
1136         if (inPlace) {
1137             v1.combineToSelf(1.0, 1.0, v2);
1138         } else {
1139             v1.combine(1.0, 1.0, v2);
1140         }
1141     }
1142 
1143     @Test
1144     public void testCombineSameType() {
1145         doTestCombine(false, false);
1146     }
1147 
1148     @Test
1149     public void testCombineMixedTypes() {
1150         doTestCombine(false, true);
1151     }
1152 
1153     @Test(expected = MathIllegalArgumentException.class)
1154     public void testCombineDimensionMismatchSameType() {
1155         doTestCombineDimensionMismatch(false, false);
1156     }
1157 
1158     @Test(expected = MathIllegalArgumentException.class)
1159     public void testCombineDimensionMismatchMixedTypes() {
1160         doTestCombineDimensionMismatch(false, true);
1161     }
1162 
1163     @Test
1164     public void testCombineToSelfSameType() {
1165         doTestCombine(true, false);
1166     }
1167 
1168     @Test
1169     public void testCombineToSelfMixedTypes() {
1170         doTestCombine(true, true);
1171     }
1172 
1173     @Test(expected = MathIllegalArgumentException.class)
1174     public void testCombineToSelfDimensionMismatchSameType() {
1175         doTestCombineDimensionMismatch(true, false);
1176     }
1177 
1178     @Test(expected = MathIllegalArgumentException.class)
1179     public void testCombineToSelfDimensionMismatchMixedTypes() {
1180         doTestCombineDimensionMismatch(true, true);
1181     }
1182 
1183     @Test
1184     public void testCopy() {
1185         final RealVector v = create(values);
1186         final RealVector w = v.copy();
1187         Assert.assertNotSame(v, w);
1188         UnitTestUtils.assertEquals("", values, w, 0d);
1189     }
1190 
1191     private void doTestDotProductRegularValues(final boolean mixed) {
1192         final double x = getPreferredEntryValue();
1193         final double[] data1 = {
1194             x, 1d, x, x, 2d, x, x, x, 3d, x, x, x, x
1195         };
1196         final double[] data2 = {
1197             5d, -6d, 7d, x, x, -8d, -9d, 10d, 11d, x, 12d, 13d, -15d
1198         };
1199         double expected = 0d;
1200         for (int i = 0; i < data1.length; i++){
1201             expected += data1[i] * data2[i];
1202         }
1203         final RealVector v1 = create(data1);
1204         final RealVector v2;
1205         if (mixed) {
1206             v2 = createAlien(data2);
1207         } else {
1208             v2 = create(data2);
1209         }
1210         final double actual = v1.dotProduct(v2);
1211         Assert.assertEquals("", expected, actual, 0d);
1212     }
1213 
1214     private void doTestDotProductSpecialValues(final boolean mixed) {
1215         for (int i = 0; i < values.length; i++) {
1216             final double[] data1 = {
1217                 values[i]
1218             };
1219             final RealVector v1 = create(data1);
1220             for (int j = 0; j < values.length; j++) {
1221                 final double[] data2 = {
1222                     values[j]
1223                 };
1224                 final RealVector v2;
1225                 if (mixed) {
1226                     v2 = createAlien(data2);
1227                 } else {
1228                     v2 = create(data2);
1229                 }
1230                 final double expected = data1[0] * data2[0];
1231                 final double actual = v1.dotProduct(v2);
1232                 Assert.assertEquals(data1[0] + " * " + data2[0], expected,
1233                     actual, 0d);
1234             }
1235         }
1236     }
1237 
1238     private void doTestDotProductDimensionMismatch(final boolean mixed) {
1239         final double[] data1 = new double[10];
1240         final double[] data2 = new double[data1.length + 1];
1241         final RealVector v1 = create(data1);
1242         final RealVector v2;
1243         if (mixed) {
1244             v2 = createAlien(data2);
1245         } else {
1246             v2 = create(data2);
1247         }
1248         v1.dotProduct(v2);
1249     }
1250 
1251     @Test
1252     public void testDotProductSameType() {
1253         doTestDotProductRegularValues(false);
1254         doTestDotProductSpecialValues(false);
1255     }
1256 
1257     @Test(expected=MathIllegalArgumentException.class)
1258     public void testDotProductDimensionMismatchSameType() {
1259         doTestDotProductDimensionMismatch(false);
1260     }
1261 
1262     @Test
1263     public void testDotProductMixedTypes() {
1264         doTestDotProductRegularValues(true);
1265         doTestDotProductSpecialValues(true);
1266     }
1267 
1268     @Test(expected=MathIllegalArgumentException.class)
1269     public void testDotProductDimensionMismatchMixedTypes() {
1270         doTestDotProductDimensionMismatch(true);
1271     }
1272 
1273     private void doTestCosine(final boolean mixed) {
1274         final double x = getPreferredEntryValue();
1275         final double[] data1 = {
1276             x, 1d, x, x, 2d, x, x, x, 3d, x, x, x, x
1277         };
1278         final double[] data2 = {
1279             5d, -6d, 7d, x, x, -8d, -9d, 10d, 11d, x, 12d, 13d, -15d
1280         };
1281         double norm1 = 0d;
1282         double norm2 = 0d;
1283         double dotProduct = 0d;
1284         for (int i = 0; i < data1.length; i++){
1285             norm1 += data1[i] * data1[i];
1286             norm2 += data2[i] * data2[i];
1287             dotProduct += data1[i] * data2[i];
1288         }
1289         norm1 = FastMath.sqrt(norm1);
1290         norm2 = FastMath.sqrt(norm2);
1291         final double expected = dotProduct / (norm1 * norm2);
1292         final RealVector v1 = create(data1);
1293         final RealVector v2;
1294         if (mixed) {
1295             v2 = createAlien(data2);
1296         } else {
1297             v2 = create(data2);
1298         }
1299         final double actual = v1.cosine(v2);
1300         Assert.assertEquals("", expected, actual, 0d);
1301 
1302     }
1303 
1304     @Test
1305     public void testCosineSameType() {
1306         doTestCosine(false);
1307     }
1308 
1309     @Test
1310     public void testCosineMixedTypes() {
1311         doTestCosine(true);
1312     }
1313 
1314     @Test(expected=MathRuntimeException.class)
1315     public void testCosineLeftNullVector() {
1316         final RealVector v = create(new double[] {0, 0, 0});
1317         final RealVector w = create(new double[] {1, 0, 0});
1318         v.cosine(w);
1319     }
1320 
1321     @Test(expected=MathRuntimeException.class)
1322     public void testCosineRightNullVector() {
1323         final RealVector v = create(new double[] {0, 0, 0});
1324         final RealVector w = create(new double[] {1, 0, 0});
1325         w.cosine(v);
1326     }
1327 
1328     @Test(expected=MathIllegalArgumentException.class)
1329     public void testCosineDimensionMismatch() {
1330         final RealVector v = create(new double[] {1, 2, 3});
1331         final RealVector w = create(new double[] {1, 2, 3, 4});
1332         v.cosine(w);
1333     }
1334 
1335     @Test
1336     public void testEquals() {
1337         final RealVector v = create(new double[] { 0, 1, 2 });
1338 
1339         Assert.assertTrue(v.equals(v));
1340         Assert.assertTrue(v.equals(v.copy()));
1341         Assert.assertFalse(v.equals(null));
1342         Assert.assertFalse(v.equals(v.getSubVector(0, v.getDimension() - 1)));
1343         Assert.assertTrue(v.equals(v.getSubVector(0, v.getDimension())));
1344     }
1345 
1346     @Test
1347     public void testSerial()  {
1348         RealVector v = create(new double[] { 0, 1, 2 });
1349         Assert.assertEquals(v,UnitTestUtils.serializeAndRecover(v));
1350     }
1351 
1352     @Test
1353     public void testMinMax() {
1354         final RealVector v1 = create(new double[] {0, -6, 4, 12, 7});
1355         Assert.assertEquals(1, v1.getMinIndex());
1356         Assert.assertEquals(-6, v1.getMinValue(), 1.0e-12);
1357         Assert.assertEquals(3, v1.getMaxIndex());
1358         Assert.assertEquals(12, v1.getMaxValue(), 1.0e-12);
1359         final RealVector v2 = create(new double[] {Double.NaN, 3, Double.NaN, -2});
1360         Assert.assertEquals(3, v2.getMinIndex());
1361         Assert.assertEquals(-2, v2.getMinValue(), 1.0e-12);
1362         Assert.assertEquals(1, v2.getMaxIndex());
1363         Assert.assertEquals(3, v2.getMaxValue(), 1.0e-12);
1364         final RealVector v3 = create(new double[] {Double.NaN, Double.NaN});
1365         Assert.assertEquals(-1, v3.getMinIndex());
1366         Assert.assertTrue(Double.isNaN(v3.getMinValue()));
1367         Assert.assertEquals(-1, v3.getMaxIndex());
1368         Assert.assertTrue(Double.isNaN(v3.getMaxValue()));
1369         final RealVector v4 = create(new double[0]);
1370         Assert.assertEquals(-1, v4.getMinIndex());
1371         Assert.assertTrue(Double.isNaN(v4.getMinValue()));
1372         Assert.assertEquals(-1, v4.getMaxIndex());
1373         Assert.assertTrue(Double.isNaN(v4.getMaxValue()));
1374     }
1375 
1376     /*
1377      * TESTS OF THE VISITOR PATTERN
1378      */
1379 
1380     /** The whole vector is visited. */
1381     @Test
1382     public void testWalkInDefaultOrderPreservingVisitor1() {
1383         final double[] data = new double[] {
1384             0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d
1385         };
1386         final RealVector v = create(data);
1387         final RealVectorPreservingVisitor visitor;
1388         visitor = new RealVectorPreservingVisitor() {
1389 
1390             private int expectedIndex;
1391 
1392             @Override
1393             public void visit(final int actualIndex, final double actualValue) {
1394                 Assert.assertEquals(expectedIndex, actualIndex);
1395                 Assert.assertEquals(Integer.toString(actualIndex),
1396                                     data[actualIndex], actualValue, 0d);
1397                 ++expectedIndex;
1398             }
1399 
1400             @Override
1401             public void start(final int actualSize, final int actualStart,
1402                               final int actualEnd) {
1403                 Assert.assertEquals(data.length, actualSize);
1404                 Assert.assertEquals(0, actualStart);
1405                 Assert.assertEquals(data.length - 1, actualEnd);
1406                 expectedIndex = 0;
1407             }
1408 
1409             @Override
1410             public double end() {
1411                 return 0.0;
1412             }
1413         };
1414         v.walkInDefaultOrder(visitor);
1415     }
1416 
1417     /** Visiting an invalid subvector. */
1418     @Test
1419     public void testWalkInDefaultOrderPreservingVisitor2() {
1420         final RealVector v = create(new double[5]);
1421         final RealVectorPreservingVisitor visitor;
1422         visitor = new RealVectorPreservingVisitor() {
1423 
1424             @Override
1425             public void visit(int index, double value) {
1426                 // Do nothing
1427             }
1428 
1429             @Override
1430             public void start(int dimension, int start, int end) {
1431                 // Do nothing
1432             }
1433 
1434             @Override
1435             public double end() {
1436                 return 0.0;
1437             }
1438         };
1439         try {
1440             v.walkInDefaultOrder(visitor, -1, 4);
1441             Assert.fail();
1442         } catch (MathIllegalArgumentException e) {
1443             // Expected behavior
1444         }
1445         try {
1446             v.walkInDefaultOrder(visitor, 5, 4);
1447             Assert.fail();
1448         } catch (MathIllegalArgumentException e) {
1449             // Expected behavior
1450         }
1451         try {
1452             v.walkInDefaultOrder(visitor, 0, -1);
1453             Assert.fail();
1454         } catch (MathIllegalArgumentException e) {
1455             // Expected behavior
1456         }
1457         try {
1458             v.walkInDefaultOrder(visitor, 0, 5);
1459             Assert.fail();
1460         } catch (MathIllegalArgumentException e) {
1461             // Expected behavior
1462         }
1463         try {
1464             v.walkInDefaultOrder(visitor, 4, 0);
1465             Assert.fail();
1466         } catch (MathIllegalArgumentException e) {
1467             // Expected behavior
1468         }
1469     }
1470 
1471     /** Visiting a valid subvector. */
1472     @Test
1473     public void testWalkInDefaultOrderPreservingVisitor3() {
1474         final double[] data = new double[] {
1475             0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d
1476         };
1477         final int expectedStart = 2;
1478         final int expectedEnd = 7;
1479         final RealVector v = create(data);
1480         final RealVectorPreservingVisitor visitor;
1481         visitor = new RealVectorPreservingVisitor() {
1482 
1483             private int expectedIndex;
1484 
1485             @Override
1486             public void visit(final int actualIndex, final double actualValue) {
1487                 Assert.assertEquals(expectedIndex, actualIndex);
1488                 Assert.assertEquals(Integer.toString(actualIndex),
1489                                     data[actualIndex], actualValue, 0d);
1490                 ++expectedIndex;
1491             }
1492 
1493             @Override
1494             public void start(final int actualSize, final int actualStart,
1495                               final int actualEnd) {
1496                 Assert.assertEquals(data.length, actualSize);
1497                 Assert.assertEquals(expectedStart, actualStart);
1498                 Assert.assertEquals(expectedEnd, actualEnd);
1499                 expectedIndex = expectedStart;
1500             }
1501 
1502             @Override
1503             public double end() {
1504                 return 0.0;
1505             }
1506         };
1507         v.walkInDefaultOrder(visitor, expectedStart, expectedEnd);
1508     }
1509 
1510     /** The whole vector is visited. */
1511     @Test
1512     public void testWalkInOptimizedOrderPreservingVisitor1() {
1513         final double[] data = new double[] {
1514             0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d
1515         };
1516         final RealVector v = create(data);
1517         final RealVectorPreservingVisitor visitor;
1518         visitor = new RealVectorPreservingVisitor() {
1519             private final boolean[] visited = new boolean[data.length];
1520 
1521             @Override
1522             public void visit(final int actualIndex, final double actualValue) {
1523                 visited[actualIndex] = true;
1524                 Assert.assertEquals(Integer.toString(actualIndex),
1525                                     data[actualIndex], actualValue, 0d);
1526             }
1527 
1528             @Override
1529             public void start(final int actualSize, final int actualStart,
1530                               final int actualEnd) {
1531                 Assert.assertEquals(data.length, actualSize);
1532                 Assert.assertEquals(0, actualStart);
1533                 Assert.assertEquals(data.length - 1, actualEnd);
1534                 Arrays.fill(visited, false);
1535             }
1536 
1537             @Override
1538             public double end() {
1539                 for (int i = 0; i < data.length; i++) {
1540                     Assert.assertTrue("entry " + i + "has not been visited",
1541                                       visited[i]);
1542                 }
1543                 return 0.0;
1544             }
1545         };
1546         v.walkInOptimizedOrder(visitor);
1547     }
1548 
1549     /** Visiting an invalid subvector. */
1550     @Test
1551     public void testWalkInOptimizedOrderPreservingVisitor2() {
1552         final RealVector v = create(new double[5]);
1553         final RealVectorPreservingVisitor visitor;
1554         visitor = new RealVectorPreservingVisitor() {
1555 
1556             @Override
1557             public void visit(int index, double value) {
1558                 // Do nothing
1559             }
1560 
1561             @Override
1562             public void start(int dimension, int start, int end) {
1563                 // Do nothing
1564             }
1565 
1566             @Override
1567             public double end() {
1568                 return 0.0;
1569             }
1570         };
1571         try {
1572             v.walkInOptimizedOrder(visitor, -1, 4);
1573             Assert.fail();
1574         } catch (MathIllegalArgumentException e) {
1575             // Expected behavior
1576         }
1577         try {
1578             v.walkInOptimizedOrder(visitor, 5, 4);
1579             Assert.fail();
1580         } catch (MathIllegalArgumentException e) {
1581             // Expected behavior
1582         }
1583         try {
1584             v.walkInOptimizedOrder(visitor, 0, -1);
1585             Assert.fail();
1586         } catch (MathIllegalArgumentException e) {
1587             // Expected behavior
1588         }
1589         try {
1590             v.walkInOptimizedOrder(visitor, 0, 5);
1591             Assert.fail();
1592         } catch (MathIllegalArgumentException e) {
1593             // Expected behavior
1594         }
1595         try {
1596             v.walkInOptimizedOrder(visitor, 4, 0);
1597             Assert.fail();
1598         } catch (MathIllegalArgumentException e) {
1599             // Expected behavior
1600         }
1601     }
1602 
1603     /** Visiting a valid subvector. */
1604     @Test
1605     public void testWalkInOptimizedOrderPreservingVisitor3() {
1606         final double[] data = new double[] {
1607             0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d
1608         };
1609         final int expectedStart = 2;
1610         final int expectedEnd = 7;
1611         final RealVector v = create(data);
1612         final RealVectorPreservingVisitor visitor;
1613         visitor = new RealVectorPreservingVisitor() {
1614             private final boolean[] visited = new boolean[data.length];
1615 
1616             @Override
1617             public void visit(final int actualIndex, final double actualValue) {
1618                 Assert.assertEquals(Integer.toString(actualIndex),
1619                                     data[actualIndex], actualValue, 0d);
1620                 visited[actualIndex] = true;
1621             }
1622 
1623             @Override
1624             public void start(final int actualSize, final int actualStart,
1625                               final int actualEnd) {
1626                 Assert.assertEquals(data.length, actualSize);
1627                 Assert.assertEquals(expectedStart, actualStart);
1628                 Assert.assertEquals(expectedEnd, actualEnd);
1629                 Arrays.fill(visited, true);
1630             }
1631 
1632             @Override
1633             public double end() {
1634                 for (int i = expectedStart; i <= expectedEnd; i++) {
1635                     Assert.assertTrue("entry " + i + "has not been visited",
1636                                       visited[i]);
1637                 }
1638                 return 0.0;
1639             }
1640         };
1641         v.walkInOptimizedOrder(visitor, expectedStart, expectedEnd);
1642     }
1643 
1644     /** The whole vector is visited. */
1645     @Test
1646     public void testWalkInDefaultOrderChangingVisitor1() {
1647         final double[] data = new double[] {
1648             0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d
1649         };
1650         final RealVector v = create(data);
1651         final RealVectorChangingVisitor visitor;
1652         visitor = new RealVectorChangingVisitor() {
1653 
1654             private int expectedIndex;
1655 
1656             @Override
1657             public double visit(final int actualIndex, final double actualValue) {
1658                 Assert.assertEquals(expectedIndex, actualIndex);
1659                 Assert.assertEquals(Integer.toString(actualIndex),
1660                                     data[actualIndex], actualValue, 0d);
1661                 ++expectedIndex;
1662                 return actualIndex + actualValue;
1663             }
1664 
1665             @Override
1666             public void start(final int actualSize, final int actualStart,
1667                               final int actualEnd) {
1668                 Assert.assertEquals(data.length, actualSize);
1669                 Assert.assertEquals(0, actualStart);
1670                 Assert.assertEquals(data.length - 1, actualEnd);
1671                 expectedIndex = 0;
1672             }
1673 
1674             @Override
1675             public double end() {
1676                 return 0.0;
1677             }
1678         };
1679         v.walkInDefaultOrder(visitor);
1680         for (int i = 0; i < data.length; i++) {
1681             Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0);
1682         }
1683     }
1684 
1685     /** Visiting an invalid subvector. */
1686     @Test
1687     public void testWalkInDefaultOrderChangingVisitor2() {
1688         final RealVector v = create(new double[5]);
1689         final RealVectorChangingVisitor visitor;
1690         visitor = new RealVectorChangingVisitor() {
1691 
1692             @Override
1693             public double visit(int index, double value) {
1694                 return 0.0;
1695             }
1696 
1697             @Override
1698             public void start(int dimension, int start, int end) {
1699                 // Do nothing
1700             }
1701 
1702             @Override
1703             public double end() {
1704                 return 0.0;
1705             }
1706         };
1707         try {
1708             v.walkInDefaultOrder(visitor, -1, 4);
1709             Assert.fail();
1710         } catch (MathIllegalArgumentException e) {
1711             // Expected behavior
1712         }
1713         try {
1714             v.walkInDefaultOrder(visitor, 5, 4);
1715             Assert.fail();
1716         } catch (MathIllegalArgumentException e) {
1717             // Expected behavior
1718         }
1719         try {
1720             v.walkInDefaultOrder(visitor, 0, -1);
1721             Assert.fail();
1722         } catch (MathIllegalArgumentException e) {
1723             // Expected behavior
1724         }
1725         try {
1726             v.walkInDefaultOrder(visitor, 0, 5);
1727             Assert.fail();
1728         } catch (MathIllegalArgumentException e) {
1729             // Expected behavior
1730         }
1731         try {
1732             v.walkInDefaultOrder(visitor, 4, 0);
1733             Assert.fail();
1734         } catch (MathIllegalArgumentException e) {
1735             // Expected behavior
1736         }
1737     }
1738 
1739     /** Visiting a valid subvector. */
1740     @Test
1741     public void testWalkInDefaultOrderChangingVisitor3() {
1742         final double[] data = new double[] {
1743             0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d
1744         };
1745         final int expectedStart = 2;
1746         final int expectedEnd = 7;
1747         final RealVector v = create(data);
1748         final RealVectorChangingVisitor visitor;
1749         visitor = new RealVectorChangingVisitor() {
1750 
1751             private int expectedIndex;
1752 
1753             @Override
1754             public double visit(final int actualIndex, final double actualValue) {
1755                 Assert.assertEquals(expectedIndex, actualIndex);
1756                 Assert.assertEquals(Integer.toString(actualIndex),
1757                                     data[actualIndex], actualValue, 0d);
1758                 ++expectedIndex;
1759                 return actualIndex + actualValue;
1760             }
1761 
1762             @Override
1763             public void start(final int actualSize, final int actualStart,
1764                               final int actualEnd) {
1765                 Assert.assertEquals(data.length, actualSize);
1766                 Assert.assertEquals(expectedStart, actualStart);
1767                 Assert.assertEquals(expectedEnd, actualEnd);
1768                 expectedIndex = expectedStart;
1769             }
1770 
1771             @Override
1772             public double end() {
1773                 return 0.0;
1774             }
1775         };
1776         v.walkInDefaultOrder(visitor, expectedStart, expectedEnd);
1777         for (int i = expectedStart; i <= expectedEnd; i++) {
1778             Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0);
1779         }
1780     }
1781 
1782     /** The whole vector is visited. */
1783     @Test
1784     public void testWalkInOptimizedOrderChangingVisitor1() {
1785         final double[] data = new double[] {
1786             0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d
1787         };
1788         final RealVector v = create(data);
1789         final RealVectorChangingVisitor visitor;
1790         visitor = new RealVectorChangingVisitor() {
1791             private final boolean[] visited = new boolean[data.length];
1792 
1793             @Override
1794             public double visit(final int actualIndex, final double actualValue) {
1795                 visited[actualIndex] = true;
1796                 Assert.assertEquals(Integer.toString(actualIndex),
1797                                     data[actualIndex], actualValue, 0d);
1798                 return actualIndex + actualValue;
1799             }
1800 
1801             @Override
1802             public void start(final int actualSize, final int actualStart,
1803                               final int actualEnd) {
1804                 Assert.assertEquals(data.length, actualSize);
1805                 Assert.assertEquals(0, actualStart);
1806                 Assert.assertEquals(data.length - 1, actualEnd);
1807                 Arrays.fill(visited, false);
1808             }
1809 
1810             @Override
1811             public double end() {
1812                 for (int i = 0; i < data.length; i++) {
1813                     Assert.assertTrue("entry " + i + "has not been visited",
1814                                       visited[i]);
1815                 }
1816                 return 0.0;
1817             }
1818         };
1819         v.walkInOptimizedOrder(visitor);
1820         for (int i = 0; i < data.length; i++) {
1821             Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0);
1822         }
1823     }
1824 
1825     /** Visiting an invalid subvector. */
1826     @Test
1827     public void testWalkInOptimizedOrderChangingVisitor2() {
1828         final RealVector v = create(new double[5]);
1829         final RealVectorChangingVisitor visitor;
1830         visitor = new RealVectorChangingVisitor() {
1831 
1832             @Override
1833             public double visit(int index, double value) {
1834                 return 0.0;
1835             }
1836 
1837             @Override
1838             public void start(int dimension, int start, int end) {
1839                 // Do nothing
1840             }
1841 
1842             @Override
1843             public double end() {
1844                 return 0.0;
1845             }
1846         };
1847         try {
1848             v.walkInOptimizedOrder(visitor, -1, 4);
1849             Assert.fail();
1850         } catch (MathIllegalArgumentException e) {
1851             // Expected behavior
1852         }
1853         try {
1854             v.walkInOptimizedOrder(visitor, 5, 4);
1855             Assert.fail();
1856         } catch (MathIllegalArgumentException e) {
1857             // Expected behavior
1858         }
1859         try {
1860             v.walkInOptimizedOrder(visitor, 0, -1);
1861             Assert.fail();
1862         } catch (MathIllegalArgumentException e) {
1863             // Expected behavior
1864         }
1865         try {
1866             v.walkInOptimizedOrder(visitor, 0, 5);
1867             Assert.fail();
1868         } catch (MathIllegalArgumentException e) {
1869             // Expected behavior
1870         }
1871         try {
1872             v.walkInOptimizedOrder(visitor, 4, 0);
1873             Assert.fail();
1874         } catch (MathIllegalArgumentException e) {
1875             // Expected behavior
1876         }
1877     }
1878 
1879     /** Visiting a valid subvector. */
1880     @Test
1881     public void testWalkInOptimizedOrderChangingVisitor3() {
1882         final double[] data = new double[] {
1883             0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d
1884         };
1885         final int expectedStart = 2;
1886         final int expectedEnd = 7;
1887         final RealVector v = create(data);
1888         final RealVectorChangingVisitor visitor;
1889         visitor = new RealVectorChangingVisitor() {
1890             private final boolean[] visited = new boolean[data.length];
1891 
1892             @Override
1893             public double visit(final int actualIndex, final double actualValue) {
1894                 Assert.assertEquals(Integer.toString(actualIndex),
1895                                     data[actualIndex], actualValue, 0d);
1896                 visited[actualIndex] = true;
1897                 return actualIndex + actualValue;
1898             }
1899 
1900             @Override
1901             public void start(final int actualSize, final int actualStart,
1902                               final int actualEnd) {
1903                 Assert.assertEquals(data.length, actualSize);
1904                 Assert.assertEquals(expectedStart, actualStart);
1905                 Assert.assertEquals(expectedEnd, actualEnd);
1906                 Arrays.fill(visited, true);
1907             }
1908 
1909             @Override
1910             public double end() {
1911                 for (int i = expectedStart; i <= expectedEnd; i++) {
1912                     Assert.assertTrue("entry " + i + "has not been visited",
1913                                       visited[i]);
1914                 }
1915                 return 0.0;
1916             }
1917         };
1918         v.walkInOptimizedOrder(visitor, expectedStart, expectedEnd);
1919         for (int i = expectedStart; i <= expectedEnd; i++) {
1920             Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0);
1921         }
1922     }
1923 
1924     /**
1925      * Minimal implementation of the {@link RealVector} abstract class, for
1926      * mixed types unit tests.
1927      */
1928     public static class RealVectorTestImpl extends RealVector
1929         implements Serializable {
1930 
1931         /** Serializable version identifier. */
1932         private static final long serialVersionUID = 20120706L;
1933 
1934         /** Entries of the vector. */
1935         protected double[] data;
1936 
1937         public RealVectorTestImpl(double[] d) {
1938             data = d.clone();
1939         }
1940 
1941         private UnsupportedOperationException unsupported() {
1942             return new UnsupportedOperationException("Not supported, unneeded for test purposes");
1943         }
1944 
1945         @Override
1946         public RealVector copy() {
1947             return new RealVectorTestImpl(data);
1948         }
1949 
1950         @Override
1951         public RealVector ebeMultiply(RealVector v) {
1952             throw unsupported();
1953         }
1954 
1955         @Override
1956         public RealVector ebeDivide(RealVector v) {
1957             throw unsupported();
1958         }
1959 
1960         @Override
1961         public double getEntry(int index) {
1962             checkIndex(index);
1963             return data[index];
1964         }
1965 
1966         @Override
1967         public int getDimension() {
1968             return data.length;
1969         }
1970 
1971         @Override
1972         public RealVector append(RealVector v) {
1973             throw unsupported();
1974         }
1975 
1976         @Override
1977         public RealVector append(double d) {
1978             throw unsupported();
1979         }
1980 
1981         @Override
1982         public RealVector getSubVector(int index, int n) {
1983             throw unsupported();
1984         }
1985 
1986         @Override
1987         public void setEntry(int index, double value) {
1988             checkIndex(index);
1989             data[index] = value;
1990         }
1991 
1992         @Override
1993         public void setSubVector(int index, RealVector v) {
1994             throw unsupported();
1995         }
1996 
1997         @Override
1998         public boolean isNaN() {
1999             throw unsupported();
2000         }
2001 
2002         @Override
2003         public boolean isInfinite() {
2004             throw unsupported();
2005         }
2006     }
2007 }