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 }