001/* 002 * Java Genetic Algorithm Library (jenetics-7.2.0). 003 * Copyright (c) 2007-2023 Franz Wilhelmstötter 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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 * Author: 018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com) 019 */ 020package io.jenetics.internal.math; 021 022import static java.lang.Double.doubleToLongBits; 023import static java.lang.Double.min; 024 025import io.jenetics.stat.LongSummary; 026 027/** 028 * This object contains mathematical helper functions. 029 * 030 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 031 * @since 1.0 032 * @version 5.2 033 */ 034public final class Basics { 035 private Basics() {} 036 037 /** 038 * Normalize the given double array, so that it sums to one. The 039 * normalization is performed in place and the same {@code values} are 040 * returned. 041 * 042 * @param values the values to normalize. 043 * @return the {@code values} array. 044 * @throws NullPointerException if the given double array is {@code null}. 045 */ 046 public static double[] normalize(final double[] values) { 047 final double sum = 1.0/DoubleAdder.sum(values); 048 for (int i = values.length; --i >= 0;) { 049 values[i] = values[i]*sum; 050 } 051 052 return values; 053 } 054 055 public static double[] normalize(final long[] values) { 056 final double[] result = new double[values.length]; 057 final double sum = 1.0/LongSummary.sum(values); 058 for (int i = values.length; --i >= 0;) { 059 result[i] = values[i]*sum; 060 } 061 062 return result; 063 } 064 065 /** 066 * Component wise division of the given double array. 067 * 068 * @param values the double values to divide. 069 * @param divisor the divisor. 070 * @throws NullPointerException if the given double array is {@code null}. 071 */ 072 public static void divide(final double[] values, final double divisor) { 073 for (int i = values.length; --i >= 0;) { 074 values[i] /= divisor; 075 } 076 } 077 078 /** 079 * Binary exponentiation algorithm. 080 * 081 * @param b the base number. 082 * @param e the exponent. 083 * @return {@code b^e}. 084 */ 085 public static long pow(final long b, final long e) { 086 long base = b; 087 long exp = e; 088 long result = 1; 089 090 while (exp != 0) { 091 if ((exp & 1) != 0) { 092 result *= base; 093 } 094 exp >>>= 1; 095 base *= base; 096 } 097 098 return result; 099 } 100 101 public static boolean isMultiplicationSave(final int a, final int b) { 102 final long m = (long)a*(long)b; 103 return (int)m == m; 104 } 105 106 /** 107 * <i>Clamping</i> a value between a pair of boundary values. 108 * <i>Note: using clamp with floating point numbers may give unexpected 109 * results if one of the values is {@code NaN}.</i> 110 * 111 * @param v the value to <i>clamp</i> 112 * @param lo the lower bound. 113 * @param hi the upper bound. 114 * @return The clamped value: 115 * <ul> 116 * <li>{@code lo if v < lo}</li> 117 * <li>{@code hi if hi < v}</li> 118 * <li>{@code otherwise, v}</li> 119 * </ul> 120 */ 121 public static double clamp(final double v, final double lo, final double hi) { 122 return v < lo ? lo : min(v, hi); 123 } 124 125 /** 126 * Return the <a href="http://en.wikipedia.org/wiki/Unit_in_the_last_place">ULP</a> 127 * distance of the given two double values. 128 * 129 * @param a first double. 130 * @param b second double. 131 * @return the ULP distance. 132 * @throws ArithmeticException if the distance doesn't fit in a long value. 133 */ 134 public static long ulpDistance(final double a, final double b) { 135 return Math.subtractExact(ulpPosition(a), ulpPosition(b)); 136 } 137 138 /** 139 * Calculating the <a href="http://en.wikipedia.org/wiki/Unit_in_the_last_place">ULP</a> 140 * position of a double number. 141 * 142 * <pre>{@code 143 * double a = 0.0; 144 * for (int i = 0; i < 10; ++i) { 145 * a = Math.nextAfter(a, Double.POSITIVE_INFINITY); 146 * } 147 * 148 * for (int i = 0; i < 19; ++i) { 149 * a = Math.nextAfter(a, Double.NEGATIVE_INFINITY); 150 * System.out.println( 151 * a + "\t" + ulpPosition(a) + "\t" + ulpDistance(0.0, a) 152 * ); 153 * } 154 * }</pre> 155 * 156 * The code fragment above will create the following output: 157 * <pre> 158 * 4.4E-323 9 9 159 * 4.0E-323 8 8 160 * 3.5E-323 7 7 161 * 3.0E-323 6 6 162 * 2.5E-323 5 5 163 * 2.0E-323 4 4 164 * 1.5E-323 3 3 165 * 1.0E-323 2 2 166 * 4.9E-324 1 1 167 * 0.0 0 0 168 * -4.9E-324 -1 1 169 * -1.0E-323 -2 2 170 * -1.5E-323 -3 3 171 * -2.0E-323 -4 4 172 * -2.5E-323 -5 5 173 * -3.0E-323 -6 6 174 * -3.5E-323 -7 7 175 * -4.0E-323 -8 8 176 * -4.4E-323 -9 9 177 * </pre> 178 * 179 * @param a the double number. 180 * @return the ULP position. 181 */ 182 public static long ulpPosition(final double a) { 183 long t = doubleToLongBits(a); 184 if (t < 0) { 185 t = Long.MIN_VALUE - t; 186 } 187 return t; 188 } 189 190}