001/*
002 * Java Genetic Algorithm Library (jenetics-7.1.0).
003 * Copyright (c) 2007-2022 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 sum 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}