001 /*
002 * Java Genetic Algorithm Library (jenetics-4.0.0).
003 * Copyright (c) 2007-2017 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 */
020 package io.jenetics;
021
022 import static java.lang.String.format;
023 import static io.jenetics.util.RandomRegistry.getRandom;
024
025 import java.io.Serializable;
026 import java.util.Random;
027
028 import io.jenetics.internal.math.random;
029 import io.jenetics.util.ISeq;
030 import io.jenetics.util.IntRange;
031 import io.jenetics.util.LongRange;
032 import io.jenetics.util.MSeq;
033 import io.jenetics.util.Mean;
034
035 /**
036 * NumericGene implementation which holds a 64 bit integer number.
037 *
038 * <p>This is a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html">
039 * value-based</a> class; use of identity-sensitive operations (including
040 * reference equality ({@code ==}), identity hash code, or synchronization) on
041 * instances of {@code LongGene} may have unpredictable results and should
042 * be avoided.
043 *
044 * @see LongChromosome
045 *
046 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
047 * @since 1.6
048 * @version 4.0
049 */
050 public final class LongGene
051 extends AbstractNumericGene<Long, LongGene>
052 implements
053 NumericGene<Long, LongGene>,
054 Mean<LongGene>,
055 Comparable<LongGene>,
056 Serializable
057 {
058
059 private static final long serialVersionUID = 1L;
060
061 /**
062 * Create a new random {@code LongGene} with the given value and the
063 * given range. If the {@code value} isn't within the interval [min, max],
064 * no exception is thrown. In this case the method
065 * {@link LongGene#isValid()} returns {@code false}.
066 *
067 * @param value the value of the gene.
068 * @param min the minimal valid value of this gene (inclusively).
069 * @param max the maximal valid value of this gene (inclusively).
070 * @throws NullPointerException if one of the arguments is {@code null}.
071 */
072 LongGene(final Long value, final Long min, final Long max) {
073 super(value, min, max);
074 }
075
076 @Override
077 public int compareTo(final LongGene other) {
078 return _value.compareTo(other._value);
079 }
080
081 /**
082 * Create a new random {@code LongGene} with the given value and the
083 * given range. If the {@code value} isn't within the interval [min, max],
084 * no exception is thrown. In this case the method
085 * {@link LongGene#isValid()} returns {@code false}.
086 *
087 * @param value the value of the gene.
088 * @param min the minimal valid value of this gene (inclusively).
089 * @param max the maximal valid value of this gene (inclusively).
090 * @return a new {@code LongGene} with the given parameters.
091 */
092 public static LongGene of(final long value, final long min, final long max) {
093 return new LongGene(value, min, max);
094 }
095
096 /**
097 * Create a new random {@code LongGene} with the given value and the
098 * given range. If the {@code value} isn't within the interval [min, max],
099 * no exception is thrown. In this case the method
100 * {@link LongGene#isValid()} returns {@code false}.
101 *
102 * @since 3.2
103 *
104 * @param value the value of the gene.
105 * @param range the long range to use
106 * @return a new random {@code LongGene}
107 * @throws NullPointerException if the given {@code range} is {@code null}.
108 */
109 public static LongGene of(final long value, final LongRange range) {
110 return new LongGene(value, range.getMin(), range.getMax());
111 }
112
113 /**
114 * Create a new random {@code LongGene}. It is guaranteed that the value of
115 * the {@code LongGene} lies in the interval [min, max].
116 *
117 * @param min the minimal valid value of this gene (inclusively).
118 * @param max the maximal valid value of this gene (inclusively).
119 * @return a new {@code LongGene} with the given parameters.
120 */
121 public static LongGene of(final long min, final long max) {
122 return of(nextLong(getRandom(), min, max), min, max);
123 }
124
125 /**
126 * Create a new random {@code LongGene}. It is guaranteed that the value of
127 * the {@code LongGene} lies in the interval [min, max].
128 *
129 * @since 3.2
130 *
131 * @param range the long range to use
132 * @return a new random {@code LongGene}
133 * @throws NullPointerException if the given {@code range} is {@code null}.
134 */
135 public static LongGene of(final LongRange range) {
136 return of(nextLong(getRandom(), range.getMin(), range.getMax()), range);
137 }
138
139 static ISeq<LongGene> seq(
140 final Long minimum,
141 final Long maximum,
142 final IntRange lengthRange
143 ) {
144 final long min = minimum;
145 final long max = maximum;
146 final Random r = getRandom();
147
148 return MSeq.<LongGene>ofLength(random.nextInt(lengthRange, r))
149 .fill(() -> new LongGene(nextLong(r, min, max), minimum, maximum))
150 .toISeq();
151 }
152
153 @Override
154 public LongGene newInstance(final Number number) {
155 return new LongGene(number.longValue(), _min, _max);
156 }
157
158 @Override
159 public LongGene newInstance() {
160 return new LongGene(
161 nextLong(getRandom(), _min, _max), _min, _max
162 );
163 }
164
165 @Override
166 public LongGene mean(final LongGene that) {
167 return new LongGene(_value + (that._value - _value)/2, _min, _max);
168 }
169
170 /**
171 * Returns a pseudo-random, uniformly distributed int value between min
172 * and max (min and max included).
173 *
174 * @param random the random engine to use for calculating the random
175 * long value
176 * @param min lower bound for generated long integer
177 * @param max upper bound for generated long integer
178 * @return a random long integer greater than or equal to {@code min}
179 * and less than or equal to {@code max}
180 * @throws IllegalArgumentException if {@code min > max}
181 * @throws NullPointerException if the given {@code random}
182 * engine is {@code null}.
183 */
184 static long nextLong(
185 final Random random,
186 final long min, final long max
187 ) {
188 if (min > max) {
189 throw new IllegalArgumentException(format(
190 "min >= max: %d >= %d.", min, max
191 ));
192 }
193
194 final long diff = (max - min) + 1;
195 long result = 0;
196
197 if (diff <= 0) {
198 do {
199 result = random.nextLong();
200 } while (result < min || result > max);
201 } else if (diff < Integer.MAX_VALUE) {
202 result = random.nextInt((int)diff) + min;
203 } else {
204 result = nextLong(random, diff) + min;
205 }
206
207 return result;
208 }
209
210 /**
211 * Returns a pseudo-random, uniformly distributed int value between 0
212 * (inclusive) and the specified value (exclusive), drawn from the given
213 * random number generator's sequence.
214 *
215 * @param random the random engine used for creating the random number.
216 * @param n the bound on the random number to be returned. Must be
217 * positive.
218 * @return the next pseudo-random, uniformly distributed int value
219 * between 0 (inclusive) and n (exclusive) from the given random
220 * number generator's sequence
221 * @throws IllegalArgumentException if n is smaller than 1.
222 * @throws NullPointerException if the given {@code random}
223 * engine is {@code null}.
224 */
225 static long nextLong(final Random random, final long n) {
226 if (n <= 0) {
227 throw new IllegalArgumentException(format(
228 "n is smaller than one: %d", n
229 ));
230 }
231
232 long bits;
233 long result;
234 do {
235 bits = random.nextLong() & 0x7fffffffffffffffL;
236 result = bits%n;
237 } while (bits - result + (n - 1) < 0);
238
239 return result;
240 }
241
242 }
|