001/* 002 * Java Genetic Algorithm Library (jenetics-7.2.0). 003 * Copyright (c) 2007-2023 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.util; 021 022import static java.lang.String.format; 023import static io.jenetics.internal.util.Hashes.hash; 024import static io.jenetics.internal.util.SerialIO.readInt; 025import static io.jenetics.internal.util.SerialIO.writeInt; 026 027import java.io.DataInput; 028import java.io.DataOutput; 029import java.io.IOException; 030import java.io.InvalidObjectException; 031import java.io.ObjectInputStream; 032import java.io.Serial; 033import java.io.Serializable; 034import java.util.stream.IntStream; 035 036/** 037 * Integer range class. 038 * 039 * @implNote 040 * This class is immutable and thread-safe. 041 * 042 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 043 * @version 6.0 044 * @since 3.2 045 */ 046public final /*record*/ class IntRange implements Serializable { 047 048 @Serial 049 private static final long serialVersionUID = 2L; 050 051 private final int _min; 052 private final int _max; 053 054 private IntRange(final int min, final int max) { 055 if (min > max) { 056 throw new IllegalArgumentException(format( 057 "Min greater than max: %s > %s", min, max 058 )); 059 } 060 061 _min = min; 062 _max = max; 063 } 064 065 /** 066 * Return the minimum value of the integer range. 067 * 068 * @return the minimum value of the integer range 069 */ 070 public int min() { 071 return _min; 072 } 073 074 /** 075 * Return the maximum value of the integer range. 076 * 077 * @return the maximum value of the integer range 078 */ 079 public int max() { 080 return _max; 081 } 082 083 /** 084 * Return the size of the {@code IntRange}: {@code max - min}. 085 * 086 * @since 3.9 087 * 088 * @return the size of the int range 089 */ 090 public int size() { 091 return _max - _min; 092 } 093 094 /** 095 * Returns a sequential ordered {@code IntStream} from {@link #min()} 096 * (inclusive) to {@link #max()} (exclusive) by an incremental step of 097 * {@code 1}. 098 * <p> 099 * An equivalent sequence of increasing values can be produced sequentially 100 * using a {@code for} loop as follows: 101 * <pre>{@code 102 * for (int i = range.min(); i < range.max(); ++i) { 103 * ... 104 * } 105 * }</pre> 106 * 107 * @since 3.4 108 * 109 * @return a sequential {@link IntStream} for the range of {@code int} 110 * elements 111 */ 112 public IntStream stream() { 113 return IntStream.range(_min, _max); 114 } 115 116 /** 117 * Create a new {@code IntRange} object with the given {@code min} and 118 * {@code max} values. 119 * 120 * @param min the lower bound of the integer range 121 * @param max the upper bound of the integer range 122 * @return a new {@code IntRange} object 123 * @throws IllegalArgumentException if {@code min > max} 124 */ 125 public static IntRange of(final int min, final int max) { 126 return new IntRange(min, max); 127 } 128 129 /** 130 * Return a new (half-open) range, which contains only the given value: 131 * {@code [value, value + 1)}. 132 * 133 * @since 4.0 134 * 135 * @param value the value of the created (half-open) integer range 136 * @return a new (half-open) range, which contains only the given value 137 */ 138 public static IntRange of(final int value) { 139 return of(value, value + 1); 140 } 141 142 @Override 143 public int hashCode() { 144 return hash(_min, hash(_max)); 145 } 146 147 @Override 148 public boolean equals(final Object obj) { 149 return obj == this || 150 obj instanceof IntRange other && 151 _min == other._min && 152 _max == other._max; 153 } 154 155 @Override 156 public String toString() { 157 return "[" + _min + ", " + _max + "]"; 158 } 159 160 161 /* ************************************************************************* 162 * Java object serialization 163 * ************************************************************************/ 164 165 @Serial 166 private Object writeReplace() { 167 return new SerialProxy(SerialProxy.INT_RANGE, this); 168 } 169 170 @Serial 171 private void readObject(final ObjectInputStream stream) 172 throws InvalidObjectException 173 { 174 throw new InvalidObjectException("Serialization proxy required."); 175 } 176 177 void write(final DataOutput out) throws IOException { 178 writeInt(_min, out); 179 writeInt(_max, out); 180 } 181 182 static IntRange read(final DataInput in) throws IOException { 183 return of(readInt(in), readInt(in)); 184 } 185 186}