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