LongGene.java
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 - min1;
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 - 10);
238 
239         return result;
240     }
241 
242 }