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 }