001/*
002 * Java Genetic Algorithm Library (jenetics-9.1.0).
003 * Copyright (c) 2007-2026 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.ext;
021
022import static java.util.Objects.requireNonNull;
023import static io.jenetics.util.RandomRegistry.random;
024
025import java.io.Serial;
026import java.io.Serializable;
027import java.math.BigInteger;
028import java.util.Objects;
029
030import io.jenetics.NumericGene;
031import io.jenetics.internal.util.Requires;
032import io.jenetics.util.ISeq;
033import io.jenetics.util.MSeq;
034import io.jenetics.util.Mean;
035import io.jenetics.util.RandomRegistry;
036
037import io.jenetics.ext.internal.util.Randoms;
038
039/**
040 * Numeric chromosome implementation which holds an arbitrary sized integer
041 * number.
042 *
043 * <p>This is a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html">
044 * value-based</a> class; use of identity-sensitive operations (including
045 * reference equality ({@code ==}), identity hash code, or synchronization) on
046 * instances of {@code IntegerGene} may have unpredictable results and should
047 * be avoided.
048 *
049 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
050 * @since 3.5
051 * @version 6.0
052 */
053public final class BigIntegerGene
054        implements
055                NumericGene<BigInteger, BigIntegerGene>,
056                Mean<BigIntegerGene>,
057                Serializable
058{
059        @Serial
060        private static final long serialVersionUID = 1L;
061
062        private static final BigInteger TWO = BigInteger.valueOf(2);
063
064        private final BigInteger _value;
065        private final BigInteger _min;
066        private final BigInteger _max;
067
068        private BigIntegerGene(
069                final BigInteger value,
070                final BigInteger min,
071                final BigInteger max
072        ) {
073                _value = requireNonNull(value);
074                _min = requireNonNull(min);
075                _max = requireNonNull(max);
076        }
077
078        @Override
079        public BigInteger allele() {
080                return _value;
081        }
082
083        @Override
084        public BigInteger min() {
085                return _min;
086        }
087
088        @Override
089        public BigInteger max() {
090                return _max;
091        }
092
093        @Override
094        public BigIntegerGene mean(final BigIntegerGene that) {
095                final BigInteger value = _value.add(that._value).divide(TWO);
096                return of(value, _min, _max);
097        }
098
099        @Override
100        public BigIntegerGene newInstance(final Number number) {
101                return of(BigInteger.valueOf(number.longValue()), _min, _max);
102        }
103
104        @Override
105        public BigIntegerGene newInstance(final BigInteger value) {
106                return of(value, _min, _max);
107        }
108
109        @Override
110        public BigIntegerGene newInstance() {
111                return of(_min, _max);
112        }
113
114        @Override
115        public int hashCode() {
116                return Objects.hash(_value, _min, _max);
117        }
118
119        @Override
120        public boolean equals(final Object obj) {
121                return obj instanceof BigIntegerGene other &&
122                        Objects.equals(other._value, _value) &&
123                        Objects.equals(other._min, _min) &&
124                        Objects.equals(other._max, _max);
125        }
126
127        @Override
128        public String toString() {
129                return String.format("[%s]", _value);
130        }
131
132        /* *************************************************************************
133         * Static factory methods.
134         **************************************************************************/
135
136        static ISeq<BigIntegerGene> seq(
137                final BigInteger minimum,
138                final BigInteger maximum,
139                final int length
140        ) {
141                Requires.positive(length);
142
143                final var r = random();
144
145                return MSeq.<BigIntegerGene>ofLength(length)
146                        .fill(() -> new BigIntegerGene(
147                                Randoms.nextBigInteger(minimum, maximum, r), minimum, maximum))
148                        .toISeq();
149        }
150
151        /**
152         * Create a new random {@code BigIntegerGene} with the given value and the
153         * given range. If the {@code value} isn't within the interval [min, max),
154         * no exception is thrown. In this case the method
155         * {@link BigIntegerGene#isValid()} returns {@code false}.
156         *
157         * @param value the value of the gene.
158         * @param min the minimal valid value of this gene (inclusively).
159         * @param max the maximal valid value of this gene (exclusively).
160         * @return a new random {@code BigIntegerGene}
161         * @throws NullPointerException if one of the arguments is {@code null}
162         */
163        public static BigIntegerGene of(
164                final BigInteger value,
165                final BigInteger min,
166                final BigInteger max
167        ) {
168                return new BigIntegerGene(value, min, max);
169        }
170
171        /**
172         * Create a new random {@code BigIntegerGene}. It is guaranteed that the
173         * value of the {@code BigIntegerGene} lies in the interval [min, max).
174         *
175         * @param min the minimal valid value of this gene (inclusively).
176         * @param max the maximal valid value of this gene (exclusively).
177         * @return a new random {@code BigIntegerGene}
178         * @throws NullPointerException if one of the arguments is {@code null}
179         */
180        public static BigIntegerGene of(final BigInteger min, final BigInteger max) {
181                return of(
182                        Randoms.nextBigInteger(min, max, RandomRegistry.random()),
183                        min,
184                        max
185                );
186        }
187
188}