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