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    *      http://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  package org.apache.commons.geometry.euclidean.internal;
18  
19  import org.apache.commons.geometry.core.Vector;
20  import org.apache.commons.numbers.arrays.SafeNorm;
21  
22  /** This class consists exclusively of static vector utility methods.
23   */
24  public final class Vectors {
25  
26      /** Private constructor. */
27      private Vectors() {}
28  
29      /** Returns true if the given value is real (ie, not NaN or infinite)
30       * and not equal to zero.
31       * @param value the value to test
32       * @return true if {@code value} is not NaN, infinite, or zero; otherwise
33       *      false
34       */
35      public static boolean isRealNonZero(final double value) {
36          return Double.isFinite(value) && value != 0.0;
37      }
38  
39      /** Throws an {@link IllegalArgumentException} if the given norm value
40       * is not real (ie, not NaN or infinite) or zero. The argument is returned
41       * to allow this method to be called inline.
42       * @param norm vector norm value
43       * @return the validated norm value
44       * @throws IllegalArgumentException if the given norm value is NaN, infinite,
45       *      or zero
46       */
47      public static double checkedNorm(final double norm) {
48          if (!isRealNonZero(norm)) {
49              throw new IllegalArgumentException("Illegal norm: " + norm);
50          }
51  
52          return norm;
53      }
54  
55      /** Returns the vector's norm value, throwing an {@link IllegalArgumentException} if the value
56       * is not real (ie, not NaN or infinite) or zero.
57       * @param vec vector to obtain the real, non-zero norm of
58       * @return the validated norm value
59       * @throws IllegalArgumentException if the vector norm value is NaN, infinite,
60       *      or zero
61       */
62      public static double checkedNorm(final Vector<?> vec) {
63          return checkedNorm(vec.norm());
64      }
65  
66      /** Attempt to normalize the given vector, returning null if the vector cannot be normalized
67       * due to the norm being NaN, infinite, or null.
68       * @param <V> Vector implementation type
69       * @param vec the vector to attempt to normalize
70       * @return the normalized vector if successful, otherwise null
71       */
72      public static <V extends Vector<V>> V tryNormalize(final V vec) {
73          final double norm = vec.norm();
74          if (isRealNonZero(norm)) {
75              return vec.normalize();
76          }
77          return null;
78      }
79  
80      /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector
81       * with the given components. This corresponds to the common notion of vector magnitude
82       * or length and is defined as the square root of the sum of the squares of all vector components.
83       * @param x vector component
84       * @return L<sub>2</sub> norm for the vector with the given components
85       * @see <a href="http://mathworld.wolfram.com/L2-Norm.html">L2 Norm</a>
86       */
87      public static double norm(final double x) {
88          return Math.abs(x);
89      }
90  
91      /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector
92       * with the given components. This corresponds to the common notion of vector magnitude
93       * or length and is defined as the square root of the sum of the squares of all vector components.
94       * @param x1 first vector component
95       * @param x2 second vector component
96       * @return L<sub>2</sub> norm for the vector with the given components
97       * @see <a href="http://mathworld.wolfram.com/L2-Norm.html">L2 Norm</a>
98       */
99      public static double norm(final double x1, final double x2) {
100         return Math.hypot(x1, x2);
101     }
102 
103     /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector
104      * with the given components. This corresponds to the common notion of vector magnitude
105      * or length and is defined as the square root of the sum of the squares of all vector components.
106      * @param x1 first vector component
107      * @param x2 second vector component
108      * @param x3 third vector component
109      * @return L<sub>2</sub> norm for the vector with the given components
110      * @see <a href="http://mathworld.wolfram.com/L2-Norm.html">L2 Norm</a>
111      */
112     public static double norm(final double x1, final double x2, final double x3) {
113         return SafeNorm.value(new double[] {x1, x2, x3});
114     }
115 
116     /** Get the square of the L<sub>2</sub> norm (also known as the Euclidean norm)
117      * for the vector with the given components. This is equal to the sum of the squares of
118      * all vector components.
119      * @param x vector component
120      * @return square of the L<sub>2</sub> norm for the vector with the given components
121      * @see #norm(double)
122      */
123     public static double normSq(final double x) {
124         return x * x;
125     }
126 
127     /** Get the square of the L<sub>2</sub> norm (also known as the Euclidean norm)
128      * for the vector with the given components. This is equal to the sum of the squares of
129      * all vector components.
130      * @param x1 first vector component
131      * @param x2 second vector component
132      * @return square of the L<sub>2</sub> norm for the vector with the given components
133      * @see #norm(double, double)
134      */
135     public static double normSq(final double x1, final double x2) {
136         return (x1 * x1) + (x2 * x2);
137     }
138 
139     /** Get the square of the L<sub>2</sub> norm (also known as the Euclidean norm)
140      * for the vector with the given components. This is equal to the sum of the squares of
141      * all vector components.
142      * @param x1 first vector component
143      * @param x2 second vector component
144      * @param x3 third vector component
145      * @return square of the L<sub>2</sub> norm for the vector with the given components
146      * @see #norm(double, double, double)
147      */
148     public static double normSq(final double x1, final double x2, final double x3) {
149         return (x1 * x1) + (x2 * x2) + (x3 * x3);
150     }
151 }