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>∞</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>∞</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 }