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 */ 017 package org.apache.commons.math3.geometry.euclidean.oned; 018 019 import java.text.NumberFormat; 020 021 import org.apache.commons.math3.exception.MathArithmeticException; 022 import org.apache.commons.math3.exception.util.LocalizedFormats; 023 import org.apache.commons.math3.geometry.Space; 024 import org.apache.commons.math3.geometry.Vector; 025 import org.apache.commons.math3.util.FastMath; 026 import org.apache.commons.math3.util.MathUtils; 027 028 /** This class represents a 1D vector. 029 * <p>Instances of this class are guaranteed to be immutable.</p> 030 * @version $Id: Vector1D.java 1416643 2012-12-03 19:37:14Z tn $ 031 * @since 3.0 032 */ 033 public 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 public double distance(Vector<Euclidean1D> p) { 222 Vector1D p3 = (Vector1D) p; 223 final double dx = p3.x - x; 224 return FastMath.abs(dx); 225 } 226 227 /** {@inheritDoc} */ 228 public double distanceInf(Vector<Euclidean1D> p) { 229 Vector1D p3 = (Vector1D) p; 230 final double dx = FastMath.abs(p3.x - x); 231 return dx; 232 } 233 234 /** {@inheritDoc} */ 235 public double distanceSq(Vector<Euclidean1D> p) { 236 Vector1D p3 = (Vector1D) p; 237 final double dx = p3.x - x; 238 return dx * dx; 239 } 240 241 /** {@inheritDoc} */ 242 public double dotProduct(final Vector<Euclidean1D> v) { 243 final Vector1D v1 = (Vector1D) v; 244 return x * v1.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 /** 284 * Test for the equality of two 1D vectors. 285 * <p> 286 * If all coordinates of two 1D vectors are exactly the same, and none are 287 * <code>Double.NaN</code>, the two 1D vectors are considered to be equal. 288 * </p> 289 * <p> 290 * <code>NaN</code> coordinates are considered to affect globally the vector 291 * and be equals to each other - i.e, if either (or all) coordinates of the 292 * 1D vector are equal to <code>Double.NaN</code>, the 1D vector is equal to 293 * {@link #NaN}. 294 * </p> 295 * 296 * @param other Object to test for equality to this 297 * @return true if two 1D vector objects are equal, false if 298 * object is null, not an instance of Vector1D, or 299 * not equal to this Vector1D instance 300 * 301 */ 302 @Override 303 public boolean equals(Object other) { 304 305 if (this == other) { 306 return true; 307 } 308 309 if (other instanceof Vector1D) { 310 final Vector1D rhs = (Vector1D)other; 311 if (rhs.isNaN()) { 312 return this.isNaN(); 313 } 314 315 return x == rhs.x; 316 } 317 return false; 318 } 319 320 /** 321 * Get a hashCode for the 1D vector. 322 * <p> 323 * All NaN values have the same hash code.</p> 324 * 325 * @return a hash code value for this object 326 */ 327 @Override 328 public int hashCode() { 329 if (isNaN()) { 330 return 7785; 331 } 332 return 997 * MathUtils.hash(x); 333 } 334 335 /** Get a string representation of this vector. 336 * @return a string representation of this vector 337 */ 338 @Override 339 public String toString() { 340 return Vector1DFormat.getInstance().format(this); 341 } 342 343 /** {@inheritDoc} */ 344 public String toString(final NumberFormat format) { 345 return new Vector1DFormat(format).format(this); 346 } 347 348 }