001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.math3.geometry.euclidean.oned;
018
019import java.text.NumberFormat;
020
021import org.apache.commons.math3.exception.MathArithmeticException;
022import org.apache.commons.math3.exception.util.LocalizedFormats;
023import org.apache.commons.math3.geometry.Point;
024import org.apache.commons.math3.geometry.Space;
025import org.apache.commons.math3.geometry.Vector;
026import org.apache.commons.math3.util.FastMath;
027import org.apache.commons.math3.util.MathUtils;
028
029/** This class represents a 1D vector.
030 * <p>Instances of this class are guaranteed to be immutable.</p>
031 * @since 3.0
032 */
033public class Vector1D implements Vector<Euclidean1D> {
034
035    /** Origin (coordinates: 0). */
036    public static final Vector1D ZERO = new Vector1D(0.0);
037
038    /** Unit (coordinates: 1). */
039    public static final Vector1D ONE  = new Vector1D(1.0);
040
041    // CHECKSTYLE: stop ConstantName
042    /** A vector with all coordinates set to NaN. */
043    public static final Vector1D NaN = new Vector1D(Double.NaN);
044    // CHECKSTYLE: resume ConstantName
045
046    /** A vector with all coordinates set to positive infinity. */
047    public static final Vector1D POSITIVE_INFINITY =
048        new Vector1D(Double.POSITIVE_INFINITY);
049
050    /** A vector with all coordinates set to negative infinity. */
051    public static final Vector1D NEGATIVE_INFINITY =
052        new Vector1D(Double.NEGATIVE_INFINITY);
053
054    /** Serializable UID. */
055    private static final long serialVersionUID = 7556674948671647925L;
056
057    /** Abscissa. */
058    private final double x;
059
060    /** Simple constructor.
061     * Build a vector from its coordinates
062     * @param x abscissa
063     * @see #getX()
064     */
065    public Vector1D(double x) {
066        this.x = x;
067    }
068
069    /** Multiplicative constructor
070     * Build a vector from another one and a scale factor.
071     * The vector built will be a * u
072     * @param a scale factor
073     * @param u base (unscaled) vector
074     */
075    public Vector1D(double a, Vector1D u) {
076        this.x = a * u.x;
077    }
078
079    /** Linear constructor
080     * Build a vector from two other ones and corresponding scale factors.
081     * The vector built will be a1 * u1 + a2 * u2
082     * @param a1 first scale factor
083     * @param u1 first base (unscaled) vector
084     * @param a2 second scale factor
085     * @param u2 second base (unscaled) vector
086     */
087    public Vector1D(double a1, Vector1D u1, double a2, Vector1D u2) {
088        this.x = a1 * u1.x + a2 * u2.x;
089    }
090
091    /** Linear constructor
092     * Build a vector from three other ones and corresponding scale factors.
093     * The vector built will be a1 * u1 + a2 * u2 + a3 * u3
094     * @param a1 first scale factor
095     * @param u1 first base (unscaled) vector
096     * @param a2 second scale factor
097     * @param u2 second base (unscaled) vector
098     * @param a3 third scale factor
099     * @param u3 third base (unscaled) vector
100     */
101    public Vector1D(double a1, Vector1D u1, double a2, Vector1D u2,
102                   double a3, Vector1D u3) {
103        this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x;
104    }
105
106    /** Linear constructor
107     * Build a vector from four other ones and corresponding scale factors.
108     * The vector built will be a1 * u1 + a2 * u2 + a3 * u3 + a4 * u4
109     * @param a1 first scale factor
110     * @param u1 first base (unscaled) vector
111     * @param a2 second scale factor
112     * @param u2 second base (unscaled) vector
113     * @param a3 third scale factor
114     * @param u3 third base (unscaled) vector
115     * @param a4 fourth scale factor
116     * @param u4 fourth base (unscaled) vector
117     */
118    public Vector1D(double a1, Vector1D u1, double a2, Vector1D u2,
119                   double a3, Vector1D u3, double a4, Vector1D u4) {
120        this.x = a1 * u1.x + a2 * u2.x + a3 * u3.x + a4 * u4.x;
121    }
122
123    /** Get the abscissa of the vector.
124     * @return abscissa of the vector
125     * @see #Vector1D(double)
126     */
127    public double getX() {
128        return x;
129    }
130
131    /** {@inheritDoc} */
132    public Space getSpace() {
133        return Euclidean1D.getInstance();
134    }
135
136    /** {@inheritDoc} */
137    public Vector1D getZero() {
138        return ZERO;
139    }
140
141    /** {@inheritDoc} */
142    public double getNorm1() {
143        return FastMath.abs(x);
144    }
145
146    /** {@inheritDoc} */
147    public double getNorm() {
148        return FastMath.abs(x);
149    }
150
151    /** {@inheritDoc} */
152    public double getNormSq() {
153        return x * x;
154    }
155
156    /** {@inheritDoc} */
157    public double getNormInf() {
158        return FastMath.abs(x);
159    }
160
161    /** {@inheritDoc} */
162    public Vector1D add(Vector<Euclidean1D> v) {
163        Vector1D v1 = (Vector1D) v;
164        return new Vector1D(x + v1.getX());
165    }
166
167    /** {@inheritDoc} */
168    public Vector1D add(double factor, Vector<Euclidean1D> v) {
169        Vector1D v1 = (Vector1D) v;
170        return new Vector1D(x + factor * v1.getX());
171    }
172
173    /** {@inheritDoc} */
174    public Vector1D subtract(Vector<Euclidean1D> p) {
175        Vector1D p3 = (Vector1D) p;
176        return new Vector1D(x - p3.x);
177    }
178
179    /** {@inheritDoc} */
180    public Vector1D subtract(double factor, Vector<Euclidean1D> v) {
181        Vector1D v1 = (Vector1D) v;
182        return new Vector1D(x - factor * v1.getX());
183    }
184
185    /** {@inheritDoc} */
186    public Vector1D normalize() throws MathArithmeticException {
187        double s = getNorm();
188        if (s == 0) {
189            throw new MathArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR);
190        }
191        return scalarMultiply(1 / s);
192    }
193    /** {@inheritDoc} */
194    public Vector1D negate() {
195        return new Vector1D(-x);
196    }
197
198    /** {@inheritDoc} */
199    public Vector1D scalarMultiply(double a) {
200        return new Vector1D(a * x);
201    }
202
203    /** {@inheritDoc} */
204    public boolean isNaN() {
205        return Double.isNaN(x);
206    }
207
208    /** {@inheritDoc} */
209    public boolean isInfinite() {
210        return !isNaN() && Double.isInfinite(x);
211    }
212
213    /** {@inheritDoc} */
214    public double distance1(Vector<Euclidean1D> p) {
215        Vector1D p3 = (Vector1D) p;
216        final double dx = FastMath.abs(p3.x - x);
217        return dx;
218    }
219
220    /** {@inheritDoc}
221     * @deprecated as of 3.3, replaced with {@link #distance(Point)}
222     */
223    @Deprecated
224    public double distance(Vector<Euclidean1D> p) {
225        return distance((Point<Euclidean1D>) p);
226    }
227
228    /** {@inheritDoc} */
229    public double distance(Point<Euclidean1D> p) {
230        Vector1D p3 = (Vector1D) p;
231        final double dx = p3.x - x;
232        return FastMath.abs(dx);
233    }
234
235    /** {@inheritDoc} */
236    public double distanceInf(Vector<Euclidean1D> p) {
237        Vector1D p3 = (Vector1D) p;
238        final double dx = FastMath.abs(p3.x - x);
239        return dx;
240    }
241
242    /** {@inheritDoc} */
243    public double distanceSq(Vector<Euclidean1D> p) {
244        Vector1D p3 = (Vector1D) p;
245        final double dx = p3.x - x;
246        return dx * dx;
247    }
248
249    /** {@inheritDoc} */
250    public double dotProduct(final Vector<Euclidean1D> v) {
251        final Vector1D v1 = (Vector1D) v;
252        return x * v1.x;
253    }
254
255    /** Compute the distance between two vectors according to the L<sub>2</sub> norm.
256     * <p>Calling this method is equivalent to calling:
257     * <code>p1.subtract(p2).getNorm()</code> except that no intermediate
258     * vector is built</p>
259     * @param p1 first vector
260     * @param p2 second vector
261     * @return the distance between p1 and p2 according to the L<sub>2</sub> norm
262     */
263    public static double distance(Vector1D p1, Vector1D p2) {
264        return p1.distance(p2);
265    }
266
267    /** Compute the distance between two vectors according to the L<sub>&infin;</sub> norm.
268     * <p>Calling this method is equivalent to calling:
269     * <code>p1.subtract(p2).getNormInf()</code> except that no intermediate
270     * vector is built</p>
271     * @param p1 first vector
272     * @param p2 second vector
273     * @return the distance between p1 and p2 according to the L<sub>&infin;</sub> norm
274     */
275    public static double distanceInf(Vector1D p1, Vector1D p2) {
276        return p1.distanceInf(p2);
277    }
278
279    /** Compute the square of the distance between two vectors.
280     * <p>Calling this method is equivalent to calling:
281     * <code>p1.subtract(p2).getNormSq()</code> except that no intermediate
282     * vector is built</p>
283     * @param p1 first vector
284     * @param p2 second vector
285     * @return the square of the distance between p1 and p2
286     */
287    public static double distanceSq(Vector1D p1, Vector1D p2) {
288        return p1.distanceSq(p2);
289    }
290
291    /**
292     * Test for the equality of two 1D vectors.
293     * <p>
294     * If all coordinates of two 1D vectors are exactly the same, and none are
295     * <code>Double.NaN</code>, the two 1D vectors are considered to be equal.
296     * </p>
297     * <p>
298     * <code>NaN</code> coordinates are considered to affect globally the vector
299     * and be equals to each other - i.e, if either (or all) coordinates of the
300     * 1D vector are equal to <code>Double.NaN</code>, the 1D vector is equal to
301     * {@link #NaN}.
302     * </p>
303     *
304     * @param other Object to test for equality to this
305     * @return true if two 1D vector objects are equal, false if
306     *         object is null, not an instance of Vector1D, or
307     *         not equal to this Vector1D instance
308     *
309     */
310    @Override
311    public boolean equals(Object other) {
312
313        if (this == other) {
314            return true;
315        }
316
317        if (other instanceof Vector1D) {
318            final Vector1D rhs = (Vector1D)other;
319            if (rhs.isNaN()) {
320                return this.isNaN();
321            }
322
323            return x == rhs.x;
324        }
325        return false;
326    }
327
328    /**
329     * Get a hashCode for the 1D vector.
330     * <p>
331     * All NaN values have the same hash code.</p>
332     *
333     * @return a hash code value for this object
334     */
335    @Override
336    public int hashCode() {
337        if (isNaN()) {
338            return 7785;
339        }
340        return 997 * MathUtils.hash(x);
341    }
342
343    /** Get a string representation of this vector.
344     * @return a string representation of this vector
345     */
346    @Override
347    public String toString() {
348        return Vector1DFormat.getInstance().format(this);
349    }
350
351    /** {@inheritDoc} */
352    public String toString(final NumberFormat format) {
353        return new Vector1DFormat(format).format(this);
354    }
355
356}