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.core.Norm;
21  import org.apache.commons.numbers.core.Sum;
22  
23  /** This class consists exclusively of static vector utility methods.
24   */
25  public final class Vectors {
26  
27      /** Private constructor. */
28      private Vectors() {}
29  
30      /** Returns true if the given value is real (ie, not NaN or infinite)
31       * and not equal to zero.
32       * @param value the value to test
33       * @return true if {@code value} is not NaN, infinite, or zero; otherwise
34       *      false
35       */
36      public static boolean isRealNonZero(final double value) {
37          return Double.isFinite(value) && value != 0.0;
38      }
39  
40      /** Throws an {@link IllegalArgumentException} if the given norm value
41       * is not real (ie, not NaN or infinite) or zero. The argument is returned
42       * to allow this method to be called inline.
43       * @param norm vector norm value
44       * @return the validated norm value
45       * @throws IllegalArgumentException if the given norm value is NaN, infinite,
46       *      or zero
47       */
48      public static double checkedNorm(final double norm) {
49          if (!isRealNonZero(norm)) {
50              throw illegalNorm(norm);
51          }
52  
53          return norm;
54      }
55  
56      /** Returns the vector's norm value, throwing an {@link IllegalArgumentException} if the value
57       * is not real (ie, not NaN or infinite) or zero.
58       * @param vec vector to obtain the real, non-zero norm of
59       * @return the validated norm value
60       * @throws IllegalArgumentException if the vector norm value is NaN, infinite,
61       *      or zero
62       */
63      public static double checkedNorm(final Vector<?> vec) {
64          return checkedNorm(vec.norm());
65      }
66  
67      /** Return an exception indicating an illegal norm value.
68       * @param norm illegal norm value
69       * @return exception indicating an illegal norm value
70       */
71      public static IllegalArgumentException illegalNorm(final double norm) {
72          return new IllegalArgumentException("Illegal norm: " + norm);
73      }
74  
75      /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector
76       * with the given components. This corresponds to the common notion of vector magnitude
77       * or length and is defined as the square root of the sum of the squares of all vector components.
78       * @param x vector component
79       * @return L<sub>2</sub> norm for the vector with the given components
80       * @see <a href="http://mathworld.wolfram.com/L2-Norm.html">L2 Norm</a>
81       */
82      public static double norm(final double x) {
83          return Math.abs(x);
84      }
85  
86      /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector
87       * with the given components. This corresponds to the common notion of vector magnitude
88       * or length and is defined as the square root of the sum of the squares of all vector components.
89       * @param x1 first vector component
90       * @param x2 second vector component
91       * @return L<sub>2</sub> norm for the vector with the given components
92       * @see <a href="http://mathworld.wolfram.com/L2-Norm.html">L2 Norm</a>
93       */
94      public static double norm(final double x1, final double x2) {
95          return Math.hypot(x1, x2);
96      }
97  
98      /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector
99       * with the given components. This corresponds to the common notion of vector magnitude
100      * or length and is defined as the square root of the sum of the squares of all vector components.
101      * @param x1 first vector component
102      * @param x2 second vector component
103      * @param x3 third vector component
104      * @return L<sub>2</sub> norm for the vector with the given components
105      * @see <a href="http://mathworld.wolfram.com/L2-Norm.html">L2 Norm</a>
106      */
107     public static double norm(final double x1, final double x2, final double x3) {
108         return Norm.EUCLIDEAN.of(x1, x2, x3);
109     }
110 
111     /** Get the square of the L<sub>2</sub> norm (also known as the Euclidean norm)
112      * for the vector with the given components. This is equal to the sum of the squares of
113      * all vector components.
114      * @param x vector component
115      * @return square of the L<sub>2</sub> norm for the vector with the given components
116      * @see #norm(double)
117      */
118     public static double normSq(final double x) {
119         return x * x;
120     }
121 
122     /** Get the square of the L<sub>2</sub> norm (also known as the Euclidean norm)
123      * for the vector with the given components. This is equal to the sum of the squares of
124      * all vector components.
125      * @param x1 first vector component
126      * @param x2 second vector component
127      * @return square of the L<sub>2</sub> norm for the vector with the given components
128      * @see #norm(double, double)
129      */
130     public static double normSq(final double x1, final double x2) {
131         return (x1 * x1) + (x2 * x2);
132     }
133 
134     /** Get the square of the L<sub>2</sub> norm (also known as the Euclidean norm)
135      * for the vector with the given components. This is equal to the sum of the squares of
136      * all vector components.
137      * @param x1 first vector component
138      * @param x2 second vector component
139      * @param x3 third vector component
140      * @return square of the L<sub>2</sub> norm for the vector with the given components
141      * @see #norm(double, double, double)
142      */
143     public static double normSq(final double x1, final double x2, final double x3) {
144         return (x1 * x1) + (x2 * x2) + (x3 * x3);
145     }
146 
147     /** Compute the linear combination \(a_1 b_1 + a_2 b_2 \) with high accuracy.
148      * @param a1 first factor of the first term
149      * @param b1 second factor of the first term
150      * @param a2 first factor of the second term
151      * @param b2 second factor of the seconf term
152      * @return linear combination.
153      * @see Sum
154      */
155     public static double linearCombination(final double a1, final double b1,
156                                            final double a2, final double b2) {
157         return Sum.create()
158                 .addProduct(a1, b1)
159                 .addProduct(a2, b2).getAsDouble();
160     }
161 
162     /** Compute the linear combination \(a_1 b_1 + a_2 b_2 + a_3 b_3 \) with high accuracy.
163      * @param a1 first factor of the first term
164      * @param b1 second factor of the first term
165      * @param a2 first factor of the second term
166      * @param b2 second factor of the seconf term
167      * @param a3 first factor of the third term
168      * @param b3 second factor of the third term
169      * @return linear combination.
170      * @see Sum
171      */
172     public static double linearCombination(final double a1, final double b1,
173                                            final double a2, final double b2,
174                                            final double a3, final double b3) {
175         return Sum.create()
176                 .addProduct(a1, b1)
177                 .addProduct(a2, b2)
178                 .addProduct(a3, b3).getAsDouble();
179     }
180 }