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.geometry.euclidean.internal; 018 019import org.apache.commons.geometry.core.Vector; 020import org.apache.commons.numbers.core.Norm; 021import org.apache.commons.numbers.core.Sum; 022 023/** This class consists exclusively of static vector utility methods. 024 */ 025public final class Vectors { 026 027 /** Private constructor. */ 028 private Vectors() {} 029 030 /** Returns true if the given value is real (ie, not NaN or infinite) 031 * and not equal to zero. 032 * @param value the value to test 033 * @return true if {@code value} is not NaN, infinite, or zero; otherwise 034 * false 035 */ 036 public static boolean isRealNonZero(final double value) { 037 return Double.isFinite(value) && value != 0.0; 038 } 039 040 /** Throws an {@link IllegalArgumentException} if the given norm value 041 * is not real (ie, not NaN or infinite) or zero. The argument is returned 042 * to allow this method to be called inline. 043 * @param norm vector norm value 044 * @return the validated norm value 045 * @throws IllegalArgumentException if the given norm value is NaN, infinite, 046 * or zero 047 */ 048 public static double checkedNorm(final double norm) { 049 if (!isRealNonZero(norm)) { 050 throw illegalNorm(norm); 051 } 052 053 return norm; 054 } 055 056 /** Returns the vector's norm value, throwing an {@link IllegalArgumentException} if the value 057 * is not real (ie, not NaN or infinite) or zero. 058 * @param vec vector to obtain the real, non-zero norm of 059 * @return the validated norm value 060 * @throws IllegalArgumentException if the vector norm value is NaN, infinite, 061 * or zero 062 */ 063 public static double checkedNorm(final Vector<?> vec) { 064 return checkedNorm(vec.norm()); 065 } 066 067 /** Return an exception indicating an illegal norm value. 068 * @param norm illegal norm value 069 * @return exception indicating an illegal norm value 070 */ 071 public static IllegalArgumentException illegalNorm(final double norm) { 072 return new IllegalArgumentException("Illegal norm: " + norm); 073 } 074 075 /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector 076 * with the given components. This corresponds to the common notion of vector magnitude 077 * or length and is defined as the square root of the sum of the squares of all vector components. 078 * @param x vector component 079 * @return L<sub>2</sub> norm for the vector with the given components 080 * @see <a href="http://mathworld.wolfram.com/L2-Norm.html">L2 Norm</a> 081 */ 082 public static double norm(final double x) { 083 return Math.abs(x); 084 } 085 086 /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector 087 * with the given components. This corresponds to the common notion of vector magnitude 088 * or length and is defined as the square root of the sum of the squares of all vector components. 089 * @param x1 first vector component 090 * @param x2 second vector component 091 * @return L<sub>2</sub> norm for the vector with the given components 092 * @see <a href="http://mathworld.wolfram.com/L2-Norm.html">L2 Norm</a> 093 */ 094 public static double norm(final double x1, final double x2) { 095 return Math.hypot(x1, x2); 096 } 097 098 /** Get the L<sub>2</sub> norm (commonly known as the Euclidean norm) for the vector 099 * 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}