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.geometry.euclidean.oned;
23  
24  import java.text.NumberFormat;
25  
26  import org.hipparchus.geometry.Space;
27  import org.hipparchus.geometry.Vector;
28  import org.hipparchus.util.FastMath;
29  import org.hipparchus.util.MathUtils;
30  
31  /** This class represents a 1D vector.
32   * <p>Instances of this class are guaranteed to be immutable.</p>
33   */
34  public class Vector1D implements Vector<Euclidean1D, Vector1D> {
35  
36      /** Origin (coordinates: 0). */
37      public static final Vector1D ZERO = new Vector1D(0.0);
38  
39      /** Unit (coordinates: 1). */
40      public static final Vector1D ONE  = new Vector1D(1.0);
41  
42      // CHECKSTYLE: stop ConstantName
43      /** A vector with all coordinates set to NaN. */
44      public static final Vector1D NaN = new Vector1D(Double.NaN);
45      // CHECKSTYLE: resume ConstantName
46  
47      /** A vector with all coordinates set to positive infinity. */
48      public static final Vector1D POSITIVE_INFINITY =
49          new Vector1D(Double.POSITIVE_INFINITY);
50  
51      /** A vector with all coordinates set to negative infinity. */
52      public static final Vector1D NEGATIVE_INFINITY =
53          new Vector1D(Double.NEGATIVE_INFINITY);
54  
55      /** Serializable UID. */
56      private static final long serialVersionUID = 7556674948671647925L;
57  
58      /** Abscissa. */
59      private final double x;
60  
61      /** Simple constructor.
62       * Build a vector from its coordinates
63       * @param x abscissa
64       * @see #getX()
65       */
66      public Vector1D(double x) {
67          this.x = x;
68      }
69  
70      /** Multiplicative constructor
71       * Build a vector from another one and a scale factor.
72       * The vector built will be a * u
73       * @param a scale factor
74       * @param u base (unscaled) vector
75       */
76      public Vector1D(double a, Vector1D u) {
77          this.x = a * u.x;
78      }
79  
80      /** Linear constructor
81       * Build a vector from two other ones and corresponding scale factors.
82       * The vector built will be a1 * u1 + a2 * u2
83       * @param a1 first scale factor
84       * @param u1 first base (unscaled) vector
85       * @param a2 second scale factor
86       * @param u2 second base (unscaled) vector
87       */
88      public Vector1D(double a1, Vector1D u1, double a2, Vector1D u2) {
89          this.x = a1 * u1.x + a2 * u2.x;
90      }
91  
92      /** Linear constructor
93       * Build a vector from three other ones and corresponding scale factors.
94       * The vector built will be a1 * u1 + a2 * u2 + a3 * u3
95       * @param a1 first scale factor
96       * @param u1 first base (unscaled) vector
97       * @param a2 second scale factor
98       * @param u2 second base (unscaled) vector
99       * @param a3 third scale factor
100      * @param u3 third base (unscaled) vector
101      */
102     public Vector1D(double a1, Vector1D u1, double a2, Vector1D u2,
103                    double a3, Vector1D u3) {
104         this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x;
105     }
106 
107     /** Linear constructor
108      * Build a vector from four other ones and corresponding scale factors.
109      * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
110      * @param a1 first scale factor
111      * @param u1 first base (unscaled) vector
112      * @param a2 second scale factor
113      * @param u2 second base (unscaled) vector
114      * @param a3 third scale factor
115      * @param u3 third base (unscaled) vector
116      * @param a4 fourth scale factor
117      * @param u4 fourth base (unscaled) vector
118      */
119     public Vector1D(double a1, Vector1D u1, double a2, Vector1D u2,
120                    double a3, Vector1D u3, double a4, Vector1D u4) {
121         this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x + a4 * u4.x;
122     }
123 
124     /** Get the abscissa of the vector.
125      * @return abscissa of the vector
126      * @see #Vector1D(double)
127      */
128     public double getX() {
129         return x;
130     }
131 
132     /** {@inheritDoc} */
133     @Override
134     public Space getSpace() {
135         return Euclidean1D.getInstance();
136     }
137 
138     /** {@inheritDoc} */
139     @Override
140     public Vector1D getZero() {
141         return ZERO;
142     }
143 
144     /** {@inheritDoc} */
145     @Override
146     public double getNorm1() {
147         return FastMath.abs(x);
148     }
149 
150     /** {@inheritDoc} */
151     @Override
152     public double getNorm() {
153         return FastMath.abs(x);
154     }
155 
156     /** {@inheritDoc} */
157     @Override
158     public double getNormSq() {
159         return x * x;
160     }
161 
162     /** {@inheritDoc} */
163     @Override
164     public double getNormInf() {
165         return FastMath.abs(x);
166     }
167 
168     /** {@inheritDoc} */
169     @Override
170     public Vector1D add(Vector1D v) {
171         return new Vector1D(x + v.getX());
172     }
173 
174     /** {@inheritDoc} */
175     @Override
176     public Vector1D add(double factor, Vector1D v) {
177         return new Vector1D(x + factor * v.getX());
178     }
179 
180     /** {@inheritDoc} */
181     @Override
182     public Vector1D subtract(Vector1D p) {
183         return new Vector1D(x - p.x);
184     }
185 
186     /** {@inheritDoc} */
187     @Override
188     public Vector1D subtract(double factor, Vector1D v) {
189         return new Vector1D(x - factor * v.getX());
190     }
191 
192     /** {@inheritDoc} */
193     @Override
194     public Vector1D negate() {
195         return new Vector1D(-x);
196     }
197 
198     /** {@inheritDoc} */
199     @Override
200     public Vector1D scalarMultiply(double a) {
201         return new Vector1D(a * x);
202     }
203 
204     /** {@inheritDoc} */
205     @Override
206     public boolean isNaN() {
207         return Double.isNaN(x);
208     }
209 
210     /** {@inheritDoc} */
211     @Override
212     public boolean isInfinite() {
213         return !isNaN() && Double.isInfinite(x);
214     }
215 
216     /** {@inheritDoc} */
217     @Override
218     public double distance1(Vector1D p) {
219         return FastMath.abs(p.x - x);
220     }
221 
222     /** {@inheritDoc} */
223     @Override
224     public double distance(Vector1D p) {
225         return FastMath.abs(p.x - x);
226     }
227 
228     /** {@inheritDoc} */
229     @Override
230     public double distanceInf(Vector1D p) {
231         return FastMath.abs(p.x - x);
232     }
233 
234     /** {@inheritDoc} */
235     @Override
236     public double distanceSq(Vector1D p) {
237         final double dx = p.x - x;
238         return dx * dx;
239     }
240 
241     /** {@inheritDoc} */
242     @Override
243     public double dotProduct(final Vector1D v) {
244         return x * v.x;
245     }
246 
247     /** Compute the distance between two vectors according to the L<sub>2</sub> norm.
248      * <p>Calling this method is equivalent to calling:
249      * <code>p1.subtract(p2).getNorm()</code> except that no intermediate
250      * vector is built</p>
251      * @param p1 first vector
252      * @param p2 second vector
253      * @return the distance between p1 and p2 according to the L<sub>2</sub> norm
254      */
255     public static double distance(Vector1D p1, Vector1D p2) {
256         return p1.distance(p2);
257     }
258 
259     /** Compute the distance between two vectors according to the L<sub>&infin;</sub> norm.
260      * <p>Calling this method is equivalent to calling:
261      * <code>p1.subtract(p2).getNormInf()</code> except that no intermediate
262      * vector is built</p>
263      * @param p1 first vector
264      * @param p2 second vector
265      * @return the distance between p1 and p2 according to the L<sub>&infin;</sub> norm
266      */
267     public static double distanceInf(Vector1D p1, Vector1D p2) {
268         return p1.distanceInf(p2);
269     }
270 
271     /** Compute the square of the distance between two vectors.
272      * <p>Calling this method is equivalent to calling:
273      * <code>p1.subtract(p2).getNormSq()</code> except that no intermediate
274      * vector is built</p>
275      * @param p1 first vector
276      * @param p2 second vector
277      * @return the square of the distance between p1 and p2
278      */
279     public static double distanceSq(Vector1D p1, Vector1D p2) {
280         return p1.distanceSq(p2);
281     }
282 
283     /** {@inheritDoc} */
284     @Override
285     public Vector1D moveTowards(final Vector1D other, final double ratio) {
286         return new Vector1D(x + ratio * (other.x - x));
287     }
288 
289     /**
290      * Test for the equality of two 1D vectors.
291      * <p>
292      * If all coordinates of two 1D vectors are exactly the same, and none are
293      * {@code Double.NaN}, the two 1D vectors are considered to be equal.
294      * </p>
295      * <p>
296      * {@code NaN} coordinates are considered to affect globally the vector
297      * and be equals to each other - i.e, if either (or all) coordinates of the
298      * 1D vector are equal to {@code Double.NaN}, the 1D vector is equal to
299      * {@link #NaN}.
300      * </p>
301      *
302      * @param other Object to test for equality to this
303      * @return true if two 1D vector objects are equal, false if
304      *         object is null, not an instance of Vector1D, or
305      *         not equal to this Vector1D instance
306      */
307     @Override
308     public boolean equals(Object other) {
309 
310         if (this == other) {
311             return true;
312         }
313 
314         if (other instanceof Vector1D) {
315             final Vector1D rhs = (Vector1D) other;
316             return x == rhs.x || isNaN() && rhs.isNaN();
317         }
318 
319         return false;
320 
321     }
322 
323     /**
324      * Test for the equality of two 1D vectors.
325      * <p>
326      * If all coordinates of two 1D vectors are exactly the same, and none are
327      * {@code NaN}, the two 1D vectors are considered to be equal.
328      * </p>
329      * <p>
330      * In compliance with IEEE754 handling, if any coordinates of any of the
331      * two vectors are {@code NaN}, then the vectors are considered different.
332      * This implies that {@link #NaN Vector1D.NaN}.equals({@link #NaN Vector1D.NaN})
333      * returns {@code false} despite the instance is checked against itself.
334      * </p>
335      *
336      * @param other Object to test for equality to this
337      * @return true if two 1D vector objects are equal, false if
338      *         object is null, not an instance of Vector1D, or
339      *         not equal to this Vector1D instance
340      *
341      * @since 2.1
342      */
343     public boolean equalsIeee754(Object other) {
344 
345         if (this == other && !isNaN()) {
346             return true;
347         }
348 
349         if (other instanceof Vector1D) {
350             final Vector1D rhs = (Vector1D) other;
351             return x == rhs.x;
352         }
353 
354         return false;
355 
356     }
357 
358     /**
359      * Get a hashCode for the 1D vector.
360      * <p>
361      * All NaN values have the same hash code.</p>
362      *
363      * @return a hash code value for this object
364      */
365     @Override
366     public int hashCode() {
367         if (isNaN()) {
368             return 7785;
369         }
370         return 997 * MathUtils.hash(x);
371     }
372 
373     /** Get a string representation of this vector.
374      * @return a string representation of this vector
375      */
376     @Override
377     public String toString() {
378         return Vector1DFormat.getVector1DFormat().format(this);
379     }
380 
381     /** {@inheritDoc} */
382     @Override
383     public String toString(final NumberFormat format) {
384         return new Vector1DFormat(format).format(this);
385     }
386 
387 }