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    *      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.geometry.euclidean.oned;
18  
19  import java.util.Comparator;
20  import java.util.regex.Pattern;
21  
22  import org.apache.commons.geometry.core.GeometryTestUtils;
23  import org.apache.commons.geometry.core.precision.DoublePrecisionContext;
24  import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext;
25  import org.apache.commons.numbers.angle.PlaneAngleRadians;
26  import org.apache.commons.numbers.core.Precision;
27  import org.junit.Assert;
28  import org.junit.Test;
29  
30  public class Vector1DTest {
31  
32      private static final double TEST_TOLERANCE = 1e-15;
33  
34      @Test
35      public void testConstants() {
36          // act/assert
37          checkVector(Vector1D.ZERO, 0.0);
38          checkVector(Vector1D.Unit.PLUS, 1.0);
39          checkVector(Vector1D.Unit.MINUS, -1.0);
40          checkVector(Vector1D.NaN, Double.NaN);
41          checkVector(Vector1D.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
42          checkVector(Vector1D.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
43      }
44  
45      @Test
46      public void testConstants_normalize() {
47          // act/assert
48          GeometryTestUtils.assertThrows(Vector1D.ZERO::normalize, IllegalArgumentException.class);
49          GeometryTestUtils.assertThrows(Vector1D.NaN::normalize, IllegalArgumentException.class);
50          GeometryTestUtils.assertThrows(Vector1D.POSITIVE_INFINITY::normalize, IllegalArgumentException.class);
51          GeometryTestUtils.assertThrows(Vector1D.NEGATIVE_INFINITY::normalize, IllegalArgumentException.class);
52  
53          Assert.assertSame(Vector1D.Unit.PLUS, Vector1D.Unit.PLUS.normalize());
54          Assert.assertSame(Vector1D.Unit.MINUS, Vector1D.Unit.MINUS.normalize());
55      }
56  
57      @Test
58      public void testCoordinateAscendingOrderComparator() {
59          // arrange
60          final Comparator<Vector1D> cmp = Vector1D.COORDINATE_ASCENDING_ORDER;
61  
62          // act/assert
63          Assert.assertEquals(0, cmp.compare(Vector1D.of(1), Vector1D.of(1)));
64          Assert.assertEquals(1, cmp.compare(Vector1D.of(2), Vector1D.of(1)));
65          Assert.assertEquals(-1, cmp.compare(Vector1D.of(0), Vector1D.of(1)));
66  
67          Assert.assertEquals(0, cmp.compare(Vector1D.of(0), Vector1D.of(0)));
68          Assert.assertEquals(1, cmp.compare(Vector1D.of(1e-15), Vector1D.of(0)));
69          Assert.assertEquals(-1, cmp.compare(Vector1D.of(-1e-15), Vector1D.of(0)));
70  
71          Assert.assertEquals(-1, cmp.compare(Vector1D.of(1), null));
72          Assert.assertEquals(1, cmp.compare(null, Vector1D.of(1)));
73          Assert.assertEquals(0, cmp.compare(null, null));
74      }
75  
76      @Test
77      public void testCoordinates() {
78          // act/assert
79          Assert.assertEquals(-1, Vector1D.of(-1).getX(), 0.0);
80          Assert.assertEquals(0, Vector1D.of(0).getX(), 0.0);
81          Assert.assertEquals(1, Vector1D.of(1).getX(), 0.0);
82      }
83  
84      @Test
85      public void testDimension() {
86          // arrange
87          final Vector1D v = Vector1D.of(2);
88  
89          // act/assert
90          Assert.assertEquals(1, v.getDimension());
91      }
92  
93      @Test
94      public void testNaN() {
95          // act/assert
96          Assert.assertTrue(Vector1D.of(Double.NaN).isNaN());
97  
98          Assert.assertFalse(Vector1D.of(1).isNaN());
99          Assert.assertFalse(Vector1D.of(Double.NEGATIVE_INFINITY).isNaN());
100     }
101 
102     @Test
103     public void testInfinite() {
104         // act/assert
105         Assert.assertTrue(Vector1D.of(Double.NEGATIVE_INFINITY).isInfinite());
106         Assert.assertTrue(Vector1D.of(Double.POSITIVE_INFINITY).isInfinite());
107 
108         Assert.assertFalse(Vector1D.of(1).isInfinite());
109         Assert.assertFalse(Vector1D.of(Double.NaN).isInfinite());
110     }
111 
112     @Test
113     public void testFinite() {
114         // act/assert
115         Assert.assertTrue(Vector1D.ZERO.isFinite());
116         Assert.assertTrue(Vector1D.of(1).isFinite());
117 
118         Assert.assertFalse(Vector1D.of(Double.NEGATIVE_INFINITY).isFinite());
119         Assert.assertFalse(Vector1D.of(Double.POSITIVE_INFINITY).isFinite());
120 
121         Assert.assertFalse(Vector1D.of(Double.NaN).isFinite());
122     }
123 
124     @Test
125     public void testZero() {
126         // act
127         final Vector1D zero = Vector1D.of(1).getZero();
128 
129         // assert
130         checkVector(zero, 0.0);
131         checkVector(Vector1D.Unit.PLUS.add(zero), 1.0);
132     }
133 
134     @Test
135     public void testNorm() {
136         // act/assert
137         Assert.assertEquals(0.0, Vector1D.ZERO.norm(), TEST_TOLERANCE);
138         Assert.assertEquals(3.0, Vector1D.of(3).norm(), TEST_TOLERANCE);
139         Assert.assertEquals(3.0, Vector1D.of(-3).norm(), TEST_TOLERANCE);
140     }
141 
142     @Test
143     public void testNorm_unitVectors() {
144         // arrange
145         final Vector1D v = Vector1D.of(2.0).normalize();
146 
147         // act/assert
148         Assert.assertEquals(1.0, v.norm(), 0.0);
149     }
150 
151     @Test
152     public void testNormSq() {
153         // act/assert
154         Assert.assertEquals(0.0, Vector1D.of(0).normSq(), TEST_TOLERANCE);
155         Assert.assertEquals(9.0, Vector1D.of(3).normSq(), TEST_TOLERANCE);
156         Assert.assertEquals(9.0, Vector1D.of(-3).normSq(), TEST_TOLERANCE);
157     }
158 
159     @Test
160     public void testNormSq_unitVectors() {
161         // arrange
162         final Vector1D v = Vector1D.of(2.0).normalize();
163 
164         // act/assert
165         Assert.assertEquals(1.0, v.normSq(), 0.0);
166     }
167 
168     @Test
169     public void testWithNorm() {
170         // act/assert
171         checkVector(Vector1D.Unit.PLUS.withNorm(0.0), 0.0);
172 
173         checkVector(Vector1D.of(0.5).withNorm(2.0), 2.0);
174         checkVector(Vector1D.of(5).withNorm(3.0), 3.0);
175 
176         checkVector(Vector1D.of(-0.5).withNorm(2.0), -2.0);
177         checkVector(Vector1D.of(-5).withNorm(3.0), -3.0);
178     }
179 
180     @Test
181     public void testWithNorm_illegalNorm() {
182         // act/assert
183         GeometryTestUtils.assertThrows(() -> Vector1D.ZERO.withNorm(2.0),
184                 IllegalArgumentException.class);
185         GeometryTestUtils.assertThrows(() -> Vector1D.NaN.withNorm(2.0),
186                 IllegalArgumentException.class);
187         GeometryTestUtils.assertThrows(() -> Vector1D.POSITIVE_INFINITY.withNorm(2.0),
188                 IllegalArgumentException.class);
189         GeometryTestUtils.assertThrows(() -> Vector1D.NEGATIVE_INFINITY.withNorm(2.0),
190                 IllegalArgumentException.class);
191     }
192 
193     @Test
194     public void testWithNorm_unitVectors() {
195         // arrange
196         final Vector1D v = Vector1D.of(2.0).normalize();
197 
198         // act/assert
199         checkVector(Vector1D.Unit.PLUS.withNorm(2.5), 2.5);
200         checkVector(Vector1D.Unit.MINUS.withNorm(3.14), -3.14);
201 
202         for (double mag = -10.0; mag <= 10.0; ++mag) {
203             Assert.assertEquals(Math.abs(mag), v.withNorm(mag).norm(), TEST_TOLERANCE);
204         }
205     }
206 
207     @Test
208     public void testAdd() {
209         // arrange
210         final Vector1D v1 = Vector1D.of(1);
211         final Vector1D v2 = Vector1D.of(-3);
212         final Vector1D v3 = Vector1D.of(3);
213 
214         // act/assert
215         checkVector(v1.add(v1), 2);
216         checkVector(v1.add(v2), -2);
217         checkVector(v2.add(v1), -2);
218         checkVector(v2.add(v3), 0);
219     }
220 
221     @Test
222     public void testAdd_scaled() {
223         // arrange
224         final Vector1D v1 = Vector1D.of(1);
225         final Vector1D v2 = Vector1D.of(-3);
226         final Vector1D v3 = Vector1D.of(3);
227 
228         // act/assert
229         checkVector(v1.add(1, v1), 2);
230         checkVector(v1.add(0.5, v1), 1.5);
231         checkVector(v1.add(-1, v1), 0);
232 
233         checkVector(v1.add(0, v2), 1);
234         checkVector(v2.add(3, v1), 0);
235         checkVector(v2.add(2, v3), 3);
236     }
237 
238     @Test
239     public void testSubtract() {
240         // arrange
241         final Vector1D v1 = Vector1D.of(1);
242         final Vector1D v2 = Vector1D.of(-3);
243         final Vector1D v3 = Vector1D.of(3);
244 
245         // act/assert
246         checkVector(v1.subtract(v1), 0);
247         checkVector(v1.subtract(v2), 4);
248         checkVector(v2.subtract(v1), -4);
249         checkVector(v2.subtract(v3), -6);
250     }
251 
252     @Test
253     public void testSubtract_scaled() {
254         // arrange
255         final Vector1D v1 = Vector1D.of(1);
256         final Vector1D v2 = Vector1D.of(-3);
257         final Vector1D v3 = Vector1D.of(3);
258 
259         // act/assert
260         checkVector(v1.subtract(1, v1), 0);
261         checkVector(v1.subtract(0.5, v1), 0.5);
262         checkVector(v1.subtract(-1, v1), 2);
263 
264         checkVector(v1.subtract(0, v2), 1);
265         checkVector(v2.subtract(3, v1), -6);
266         checkVector(v2.subtract(2, v3), -9);
267     }
268 
269     @Test
270     public void testNormalize() {
271         // act/assert
272         checkVector(Vector1D.of(1).normalize(), 1);
273         checkVector(Vector1D.of(-1).normalize(), -1);
274         checkVector(Vector1D.of(5).normalize(), 1);
275         checkVector(Vector1D.of(-5).normalize(), -1);
276     }
277 
278     @Test
279     public void testNormalize_illegalNorm() {
280         // act/assert
281         GeometryTestUtils.assertThrows(() -> Vector1D.of(0.0).normalize(),
282                 IllegalArgumentException.class);
283         GeometryTestUtils.assertThrows(() -> Vector1D.of(Double.NaN).normalize(),
284                 IllegalArgumentException.class);
285         GeometryTestUtils.assertThrows(() -> Vector1D.of(Double.POSITIVE_INFINITY).normalize(),
286                 IllegalArgumentException.class);
287         GeometryTestUtils.assertThrows(() -> Vector1D.of(Double.NEGATIVE_INFINITY).normalize(),
288                 IllegalArgumentException.class);
289     }
290 
291     @Test
292     public void testNormalize_isIdempotent() {
293         // arrange
294         final Vector1D v = Vector1D.of(2).normalize();
295 
296         // act/assert
297         Assert.assertSame(v, v.normalize());
298         checkVector(v.normalize(), 1.0);
299     }
300 
301     @Test
302     public void testNegate() {
303         // act/assert
304         checkVector(Vector1D.of(0.1).negate(), -0.1);
305         checkVector(Vector1D.of(-0.1).negate(), 0.1);
306     }
307 
308     @Test
309     public void testNegate_unitVectors() {
310         // arrange
311         final Vector1D v1 = Vector1D.of(0.1).normalize();
312         final Vector1D v2 = Vector1D.of(-0.1).normalize();
313 
314         // act/assert
315         checkVector(v1.negate(), -1);
316         checkVector(v2.negate(), 1);
317     }
318 
319     @Test
320     public void testScalarMultiply() {
321         // act/assert
322         checkVector(Vector1D.of(1).multiply(3), 3);
323         checkVector(Vector1D.of(1).multiply(-3), -3);
324 
325         checkVector(Vector1D.of(1.5).multiply(7), 10.5);
326         checkVector(Vector1D.of(-1.5).multiply(7), -10.5);
327     }
328 
329     @Test
330     public void testDistance() {
331         // arrange
332         final Vector1D v1 = Vector1D.of(1);
333         final Vector1D v2 = Vector1D.of(-4);
334 
335         // act/assert
336         Assert.assertEquals(0.0, v1.distance(v1), TEST_TOLERANCE);
337 
338         Assert.assertEquals(5.0, v1.distance(v2), TEST_TOLERANCE);
339         Assert.assertEquals(5.0, v2.distance(v1), TEST_TOLERANCE);
340         Assert.assertEquals(v1.subtract(v2).norm(), v1.distance(v2), TEST_TOLERANCE);
341 
342         Assert.assertEquals(0.0, Vector1D.of(-1).distance(Vector1D.of(-1)), TEST_TOLERANCE);
343     }
344 
345     @Test
346     public void testDistanceSq() {
347         // arrange
348         final Vector1D v1 = Vector1D.of(1);
349         final Vector1D v2 = Vector1D.of(-4);
350 
351         // act/assert
352         Assert.assertEquals(0.0, Vector1D.of(-1).distanceSq(Vector1D.of(-1)), TEST_TOLERANCE);
353         Assert.assertEquals(25.0, v1.distanceSq(v2), TEST_TOLERANCE);
354         Assert.assertEquals(25.0, v2.distanceSq(v1), TEST_TOLERANCE);
355     }
356 
357     @Test
358     public void testDotProduct() {
359         // arrange
360         final Vector1D v1 = Vector1D.of(2);
361         final Vector1D v2 = Vector1D.of(-3);
362         final Vector1D v3 = Vector1D.of(3);
363 
364         // act/assert
365         Assert.assertEquals(-6.0, v1.dot(v2), TEST_TOLERANCE);
366         Assert.assertEquals(-6.0, v2.dot(v1), TEST_TOLERANCE);
367 
368         Assert.assertEquals(6.0, v1.dot(v3), TEST_TOLERANCE);
369         Assert.assertEquals(6.0, v3.dot(v1), TEST_TOLERANCE);
370     }
371 
372     @Test
373     public void testAngle() {
374         // arrange
375         final Vector1D v1 = Vector1D.of(2);
376         final Vector1D v2 = Vector1D.of(-3);
377         final Vector1D v3 = Vector1D.of(4);
378         final Vector1D v4 = Vector1D.of(-5);
379 
380         // act/assert
381         Assert.assertEquals(0.0, v1.angle(v1), TEST_TOLERANCE);
382         Assert.assertEquals(PlaneAngleRadians.PI, v1.angle(v2), TEST_TOLERANCE);
383         Assert.assertEquals(0.0, v1.angle(v3), TEST_TOLERANCE);
384         Assert.assertEquals(PlaneAngleRadians.PI, v1.angle(v4), TEST_TOLERANCE);
385 
386         Assert.assertEquals(PlaneAngleRadians.PI, v2.angle(v1), TEST_TOLERANCE);
387         Assert.assertEquals(0.0, v2.angle(v2), TEST_TOLERANCE);
388         Assert.assertEquals(PlaneAngleRadians.PI, v2.angle(v3), TEST_TOLERANCE);
389         Assert.assertEquals(0.0, v2.angle(v4), TEST_TOLERANCE);
390 
391         Assert.assertEquals(0.0, v3.angle(v1), TEST_TOLERANCE);
392         Assert.assertEquals(PlaneAngleRadians.PI, v3.angle(v2), TEST_TOLERANCE);
393         Assert.assertEquals(0.0, v3.angle(v3), TEST_TOLERANCE);
394         Assert.assertEquals(PlaneAngleRadians.PI, v3.angle(v4), TEST_TOLERANCE);
395 
396         Assert.assertEquals(PlaneAngleRadians.PI, v4.angle(v1), TEST_TOLERANCE);
397         Assert.assertEquals(0.0, v4.angle(v2), TEST_TOLERANCE);
398         Assert.assertEquals(PlaneAngleRadians.PI, v4.angle(v3), TEST_TOLERANCE);
399         Assert.assertEquals(0.0, v4.angle(v4), TEST_TOLERANCE);
400     }
401 
402     @Test
403     public void testAngle_illegalNorm() {
404         // arrange
405         final Vector1D v = Vector1D.of(1.0);
406 
407         // act/assert
408         GeometryTestUtils.assertThrows(() -> Vector1D.ZERO.angle(v),
409                 IllegalArgumentException.class);
410         GeometryTestUtils.assertThrows(() -> Vector1D.NaN.angle(v),
411                 IllegalArgumentException.class);
412         GeometryTestUtils.assertThrows(() -> Vector1D.POSITIVE_INFINITY.angle(v),
413                 IllegalArgumentException.class);
414         GeometryTestUtils.assertThrows(() -> Vector1D.NEGATIVE_INFINITY.angle(v),
415                 IllegalArgumentException.class);
416 
417         GeometryTestUtils.assertThrows(() -> v.angle(Vector1D.ZERO),
418                 IllegalArgumentException.class);
419         GeometryTestUtils.assertThrows(() -> v.angle(Vector1D.NaN),
420                 IllegalArgumentException.class);
421         GeometryTestUtils.assertThrows(() -> v.angle(Vector1D.POSITIVE_INFINITY),
422                 IllegalArgumentException.class);
423         GeometryTestUtils.assertThrows(() -> v.angle(Vector1D.NEGATIVE_INFINITY),
424                 IllegalArgumentException.class);
425     }
426 
427     @Test
428     public void testVectorTo() {
429         // arrange
430         final Vector1D v1 = Vector1D.of(1);
431         final Vector1D v2 = Vector1D.of(-4);
432         final Vector1D v3 = Vector1D.of(10);
433 
434         // act/assert
435         checkVector(v1.vectorTo(v1), 0.0);
436         checkVector(v2.vectorTo(v2), 0.0);
437         checkVector(v3.vectorTo(v3), 0.0);
438 
439         checkVector(v1.vectorTo(v2), -5.0);
440         checkVector(v2.vectorTo(v1), 5.0);
441 
442         checkVector(v1.vectorTo(v3), 9.0);
443         checkVector(v3.vectorTo(v1), -9.0);
444 
445         checkVector(v2.vectorTo(v3), 14.0);
446         checkVector(v3.vectorTo(v2), -14.0);
447     }
448 
449     @Test
450     public void testDirectionTo() {
451         // act/assert
452         final Vector1D v1 = Vector1D.of(1);
453         final Vector1D v2 = Vector1D.of(5);
454         final Vector1D v3 = Vector1D.of(-2);
455 
456         // act/assert
457         checkVector(v1.directionTo(v2), 1);
458         checkVector(v2.directionTo(v1), -1);
459 
460         checkVector(v1.directionTo(v3), -1);
461         checkVector(v3.directionTo(v1), 1);
462     }
463 
464     @Test
465     public void testDirectionTo_illegalNorm() {
466         // arrange
467         final Vector1D v = Vector1D.of(2);
468 
469         // act/assert
470         GeometryTestUtils.assertThrows(() -> Vector1D.ZERO.directionTo(Vector1D.ZERO),
471                 IllegalArgumentException.class);
472         GeometryTestUtils.assertThrows(() -> v.directionTo(v),
473                 IllegalArgumentException.class);
474         GeometryTestUtils.assertThrows(() -> v.directionTo(Vector1D.NaN),
475                 IllegalArgumentException.class);
476         GeometryTestUtils.assertThrows(() -> Vector1D.NEGATIVE_INFINITY.directionTo(v),
477                 IllegalArgumentException.class);
478         GeometryTestUtils.assertThrows(() -> v.directionTo(Vector1D.POSITIVE_INFINITY),
479                 IllegalArgumentException.class);
480     }
481 
482     @Test
483     public void testLerp() {
484         // arrange
485         final Vector1D v1 = Vector1D.of(1);
486         final Vector1D v2 = Vector1D.of(-4);
487         final Vector1D v3 = Vector1D.of(10);
488 
489         // act/assert
490         checkVector(v1.lerp(v1, 0), 1);
491         checkVector(v1.lerp(v1, 1), 1);
492 
493         checkVector(v1.lerp(v2, -0.25), 2.25);
494         checkVector(v1.lerp(v2, 0), 1);
495         checkVector(v1.lerp(v2, 0.25), -0.25);
496         checkVector(v1.lerp(v2, 0.5), -1.5);
497         checkVector(v1.lerp(v2, 0.75), -2.75);
498         checkVector(v1.lerp(v2, 1), -4);
499         checkVector(v1.lerp(v2, 1.25), -5.25);
500 
501         checkVector(v1.lerp(v3, 0), 1);
502         checkVector(v1.lerp(v3, 0.25), 3.25);
503         checkVector(v1.lerp(v3, 0.5), 5.5);
504         checkVector(v1.lerp(v3, 0.75), 7.75);
505         checkVector(v1.lerp(v3, 1), 10);
506     }
507 
508     @Test
509     public void testTransform() {
510         // arrange
511         final AffineTransformMatrix1D transform = AffineTransformMatrix1D.identity()
512                 .scale(2)
513                 .translate(1);
514 
515         final Vector1D v1 = Vector1D.of(1);
516         final Vector1D v2 = Vector1D.of(-4);
517 
518         // act/assert
519         checkVector(v1.transform(transform), 3);
520         checkVector(v2.transform(transform), -7);
521     }
522 
523     @Test
524     public void testPrecisionEquals() {
525         // arrange
526         final DoublePrecisionContext smallEps = new EpsilonDoublePrecisionContext(1e-6);
527         final DoublePrecisionContext largeEps = new EpsilonDoublePrecisionContext(1e-1);
528 
529         final Vector1D vec = Vector1D.of(1);
530 
531         // act/assert
532         Assert.assertTrue(vec.eq(vec, smallEps));
533         Assert.assertTrue(vec.eq(vec, largeEps));
534 
535         Assert.assertTrue(vec.eq(Vector1D.of(1.0000007), smallEps));
536         Assert.assertTrue(vec.eq(Vector1D.of(1.0000007), largeEps));
537 
538         Assert.assertFalse(vec.eq(Vector1D.of(1.004), smallEps));
539         Assert.assertTrue(vec.eq(Vector1D.of(1.004), largeEps));
540 
541         Assert.assertFalse(vec.eq(Vector1D.of(2), smallEps));
542         Assert.assertFalse(vec.eq(Vector1D.of(-2), largeEps));
543     }
544 
545     @Test
546     public void testIsZero() {
547         // arrange
548         final DoublePrecisionContext smallEps = new EpsilonDoublePrecisionContext(1e-6);
549         final DoublePrecisionContext largeEps = new EpsilonDoublePrecisionContext(1e-1);
550 
551         // act/assert
552         Assert.assertTrue(Vector1D.of(0.0).isZero(smallEps));
553         Assert.assertTrue(Vector1D.of(-0.0).isZero(largeEps));
554 
555         Assert.assertTrue(Vector1D.of(1e-7).isZero(smallEps));
556         Assert.assertTrue(Vector1D.of(-1e-7).isZero(largeEps));
557 
558         Assert.assertFalse(Vector1D.of(1e-2).isZero(smallEps));
559         Assert.assertTrue(Vector1D.of(-1e-2).isZero(largeEps));
560 
561         Assert.assertFalse(Vector1D.of(0.2).isZero(smallEps));
562         Assert.assertFalse(Vector1D.of(-0.2).isZero(largeEps));
563     }
564 
565     @Test
566     public void testHashCode() {
567         // arrange
568         final Vector1D u = Vector1D.of(1);
569         final Vector1D v = Vector1D.of(1 + 10 * Precision.EPSILON);
570         final Vector1D w = Vector1D.of(1);
571 
572         // act/assert
573         Assert.assertTrue(u.hashCode() != v.hashCode());
574         Assert.assertEquals(u.hashCode(), w.hashCode());
575 
576         Assert.assertEquals(Vector1D.of(Double.NaN).hashCode(), Vector1D.NaN.hashCode());
577         Assert.assertEquals(Vector1D.of(Double.NaN).hashCode(), Vector1D.of(Double.NaN).hashCode());
578     }
579 
580     @Test
581     public void testEquals() {
582         // arrange
583         final Vector1D u1 = Vector1D.of(1);
584         final Vector1D u2 = Vector1D.of(1);
585 
586         // act/assert
587         Assert.assertFalse(u1.equals(null));
588         Assert.assertFalse(u1.equals(new Object()));
589 
590         Assert.assertEquals(u1, u1);
591         Assert.assertEquals(u1, u2);
592 
593         Assert.assertNotEquals(u1, Vector1D.of(-1));
594         Assert.assertNotEquals(u1, Vector1D.of(1 + 10 * Precision.EPSILON));
595 
596         Assert.assertEquals(Vector1D.of(Double.NaN), Vector1D.of(Double.NaN));
597         Assert.assertEquals(Vector1D.of(Double.POSITIVE_INFINITY), Vector1D.of(Double.POSITIVE_INFINITY));
598         Assert.assertEquals(Vector1D.of(Double.NEGATIVE_INFINITY), Vector1D.of(Double.NEGATIVE_INFINITY));
599     }
600 
601     @Test
602     public void testEqualsAndHashCode_signedZeroConsistency() {
603         // arrange
604         final Vector1D a = Vector1D.of(0.0);
605         final Vector1D b = Vector1D.of(-0.0);
606         final Vector1D c = Vector1D.of(0.0);
607         final Vector1D d = Vector1D.of(-0.0);
608 
609         // act/assert
610         Assert.assertFalse(a.equals(b));
611         Assert.assertNotEquals(a.hashCode(), b.hashCode());
612 
613         Assert.assertTrue(a.equals(c));
614         Assert.assertEquals(a.hashCode(), c.hashCode());
615 
616         Assert.assertTrue(b.equals(d));
617         Assert.assertEquals(b.hashCode(), d.hashCode());
618     }
619 
620     @Test
621     public void testToString() {
622         // arrange
623         final Vector1D v = Vector1D.of(3);
624         final Pattern pattern = Pattern.compile("\\(3.{0,2}\\)");
625 
626         // act
627         final String str = v.toString();
628 
629         // assert
630         Assert.assertTrue("Expected string " + str + " to match regex " + pattern,
631                     pattern.matcher(str).matches());
632     }
633 
634     @Test
635     public void testParse() {
636         // act/assert
637         checkVector(Vector1D.parse("(1)"), 1);
638         checkVector(Vector1D.parse("(-1)"), -1);
639 
640         checkVector(Vector1D.parse("(0.01)"), 1e-2);
641         checkVector(Vector1D.parse("(-1e-3)"), -1e-3);
642 
643         checkVector(Vector1D.parse("(NaN)"), Double.NaN);
644 
645         checkVector(Vector1D.parse(Vector1D.ZERO.toString()), 0);
646         checkVector(Vector1D.parse(Vector1D.Unit.PLUS.toString()), 1);
647     }
648 
649     @Test(expected = IllegalArgumentException.class)
650     public void testParse_failure() {
651         // act/assert
652         Vector1D.parse("abc");
653     }
654 
655     @Test
656     public void testOf() {
657         // act/assert
658         checkVector(Vector1D.of(0), 0.0);
659         checkVector(Vector1D.of(-1), -1.0);
660         checkVector(Vector1D.of(1), 1.0);
661         checkVector(Vector1D.of(Math.PI), Math.PI);
662         checkVector(Vector1D.of(Double.NaN), Double.NaN);
663         checkVector(Vector1D.of(Double.NEGATIVE_INFINITY), Double.NEGATIVE_INFINITY);
664         checkVector(Vector1D.of(Double.POSITIVE_INFINITY), Double.POSITIVE_INFINITY);
665     }
666 
667     @Test
668     public void testUnitFrom_coordinates() {
669         // act/assert
670         checkVector(Vector1D.Unit.from(2.0), 1);
671         checkVector(Vector1D.Unit.from(-4.0), -1);
672     }
673 
674     @Test
675     public void testUnitFrom_vector() {
676         // arrange
677         final Vector1D vec = Vector1D.of(2);
678         final Vector1D unitVec = Vector1D.Unit.from(2);
679 
680         // act/assert
681         checkVector(Vector1D.Unit.from(vec), 1);
682         Assert.assertSame(unitVec, Vector1D.Unit.from(unitVec));
683     }
684 
685     @Test
686     public void testUnitFrom_illegalNorm() {
687         GeometryTestUtils.assertThrows(() -> Vector1D.Unit.from(0.0),
688                 IllegalArgumentException.class);
689         GeometryTestUtils.assertThrows(() -> Vector1D.Unit.from(Double.NaN),
690                 IllegalArgumentException.class);
691         GeometryTestUtils.assertThrows(() -> Vector1D.Unit.from(Double.NEGATIVE_INFINITY),
692                 IllegalArgumentException.class);
693         GeometryTestUtils.assertThrows(() -> Vector1D.Unit.from(Double.POSITIVE_INFINITY),
694                 IllegalArgumentException.class);
695     }
696 
697     @Test
698     public void testLinearCombination() {
699         // act/assert
700         checkVector(Vector1D.linearCombination(2, Vector1D.of(3)), 6);
701         checkVector(Vector1D.linearCombination(-2, Vector1D.of(3)), -6);
702     }
703 
704     @Test
705     public void testLinearCombination2() {
706         // act/assert
707         checkVector(Vector1D.linearCombination(
708                 2, Vector1D.of(3),
709                 5, Vector1D.of(7)), 41);
710         checkVector(Vector1D.linearCombination(
711                 2, Vector1D.of(3),
712                 -5, Vector1D.of(7)), -29);
713     }
714 
715     @Test
716     public void testLinearCombination3() {
717         // act/assert
718         checkVector(Vector1D.linearCombination(
719                 2, Vector1D.of(3),
720                 5, Vector1D.of(7),
721                 11, Vector1D.of(13)), 184);
722         checkVector(Vector1D.linearCombination(
723                 2, Vector1D.of(3),
724                 5, Vector1D.of(7),
725                 -11, Vector1D.of(13)), -102);
726     }
727 
728     @Test
729     public void testLinearCombination4() {
730         // act/assert
731         checkVector(Vector1D.linearCombination(
732                 2, Vector1D.of(3),
733                 5, Vector1D.of(7),
734                 11, Vector1D.of(13),
735                 17, Vector1D.of(19)), 507);
736         checkVector(Vector1D.linearCombination(
737                 2, Vector1D.of(3),
738                 5, Vector1D.of(7),
739                 11, Vector1D.of(13),
740                 -17, Vector1D.of(19)), -139);
741     }
742 
743     @Test
744     public void testUnitFactoryOptimization() {
745         // An already normalized vector will avoid unnecessary creation.
746         final Vector1D v = Vector1D.of(3).normalize();
747         Assert.assertSame(v, v.normalize());
748     }
749 
750     private void checkVector(final Vector1D v, final double x) {
751         Assert.assertEquals(x, v.getX(), TEST_TOLERANCE);
752     }
753 }