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