001 /*
002 * Java Genetic Algorithm Library (jenetics-1.6.0).
003 * Copyright (c) 2007-2014 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@gmx.at)
019 */
020 package org.jenetics.internal.util;
021
022 import static java.lang.String.format;
023
024 import org.jenetics.util.Copyable;
025
026 /**
027 * Abstraction for an ordered and bounded sequence of elements.
028 *
029 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
030 * @since 1.4
031 * @version 1.5 — <em>$Date: 2014-02-15 $</em>
032 */
033 public abstract class ArrayProxy<T> implements Copyable<ArrayProxy<T>> {
034
035 protected final int _start;
036 protected final int _end;
037 protected final int _length;
038
039 protected ArrayProxy(final int from, final int until) {
040 if (from < 0 || until < 0 || until < from) {
041 throw new IllegalArgumentException(format(
042 "Invalid indexes [%d, %d)", from, until
043 ));
044 }
045
046 _start = from;
047 _end = until;
048 _length = _end - _start;
049 }
050
051 /**
052 * Return the <i>array</i> element at the specified, absolute position in
053 * the {@code ArrayProxy}. The array boundaries are not checked.
054 *
055 * @param absoluteIndex absolute index of the element to return
056 * @return the <i>array</i> element at the specified absolute position
057 */
058 public abstract T __get(final int absoluteIndex);
059
060 /**
061 * Set the <i>array</i> element at the specified absolute position in the
062 * {@code ArrayProxy}. The array boundaries are not checked.
063 *
064 * @param absoluteIndex absolute index of the <i>array</i> element
065 */
066 public abstract void __set(final int absoluteIndex, final T value);
067
068 /**
069 * Return the <i>array</i> element at the specified position in the
070 * {@code ArrayProxy}. The array boundaries are not checked.
071 *
072 * @param index index of the element to return
073 * @return the <i>array</i> element at the specified position
074 */
075 public T uncheckedGet(final int index) {
076 return __get(index + _start);
077 }
078
079 /**
080 * Set the <i>array</i> element at the specified position in the
081 * {@code ArrayProxy}. The array boundaries are not checked.
082 *
083 * @param index index of the <i>array</i> element
084 */
085 public void uncheckedSet(final int index, final T value) {
086 __set(index + _start, value);
087 }
088
089 /**
090 * Return the <i>array</i> element at the specified position in the
091 * {@code ArrayProxy}.
092 *
093 * @param index index of the element to return
094 * @return the <i>array</i> element at the specified position
095 * @throws IndexOutOfBoundsException if the index it out of range
096 * (index < 0 || index >= _length).
097 */
098 public T get(final int index) {
099 checkIndex(index);
100 return __get(index + _start);
101 }
102
103 /**
104 * Set the <i>array</i> element at the specified position in the
105 * {@code ArrayProxy}
106 *
107 * @param index the index of the element to set
108 * @param value the <i>array</i> element
109 * @throws IndexOutOfBoundsException if the index it out of range
110 * (index < 0 || index >= _length).
111 */
112 public void set(final int index, final T value) {
113 checkIndex(index);
114 __set(index + _start, value);
115 }
116
117 /**
118 * Return a new sub {@code ArrayProxy} object with the given start and end
119 * indexes. The underlying array storage is not copied. With the returned
120 * sub-array proxy it is possible to <i>write through</i> the original
121 * array.
122 *
123 * @param from the start index of the new sub {@code ArrayProxy} object,
124 * inclusively.
125 * @param until the end index of the new sub {@code ArrayProxy} object,
126 * exclusively.
127 * @return a new array proxy (view) with the given start and end index.
128 * @throws IndexOutOfBoundsException if the given indexes are out of bounds.
129 */
130 public abstract ArrayProxy<T> slice(final int from, final int until);
131
132 /**
133 * Return a new sub {@code ArrayProxy} object with the given start index.
134 * The underlying array storage is not copied. With the returned sub-array
135 * proxy it is possible to <i>write through</i> the original array.
136 *
137 * @param from the start index of the new sub {@code ArrayProxy} object,
138 * inclusively.
139 * @return a new array proxy (view) with the given start index.
140 * @throws IndexOutOfBoundsException if the given indexes are out of bounds.
141 */
142 public ArrayProxy<T> slice(final int from) {
143 return slice(from, _length);
144 }
145
146 /**
147 * Swap a given range with a range of the same size with another array.
148 * Implementations of this class should replace this with a optimized
149 * version, depending on the underlying data structure.
150 *
151 * <pre>
152 * from until
153 * | |
154 * this: +---+---+---+---+---+---+---+---+---+---+---+---+
155 * +---------------+
156 * +---------------+
157 * other: +---+---+---+---+---+---+---+---+---+---+---+---+
158 * |
159 * otherFrom
160 * </pre>
161 *
162 * @param from the start index of {@code this} range, inclusively.
163 * @param until the end index of {@code this} range, exclusively.
164 * @param other the other array to swap the elements with.
165 * @param otherFrom the start index of the {@code other} array.
166 * @throws IndexOutOfBoundsException if {@code start > end} or
167 * if {@code from < 0 || until >= this.length() || otherFrom < 0 ||
168 * otherFrom + (until - from) >= other.length()}
169 */
170 public void swap(
171 final int from,
172 final int until,
173 final ArrayProxy<T> other,
174 final int otherFrom
175 ) {
176 checkIndex(from, until);
177 other.checkIndex(otherFrom, otherFrom + (until - from));
178 cloneIfSealed();
179 other.cloneIfSealed();
180
181 for (int i = (until - from); --i >= 0;) {
182 final T temp = uncheckedGet(i + from);
183 uncheckedSet(i + from, other.uncheckedGet(otherFrom + i));
184 other.uncheckedSet(otherFrom + i, temp);
185 }
186 }
187
188 /**
189 * Clone the underlying data structure of this {@code ArrayProxy} if it is
190 * sealed.
191 * <p/>
192 * The <i>default</i> implementation will look like this:
193 * [code]
194 * public void cloneIfSealed() {
195 * if (_sealed) {
196 * _array = _array.clone();
197 * _sealed = false;
198 * }
199 * }
200 * [/code]
201 */
202 public abstract void cloneIfSealed();
203
204
205 /**
206 * Set the seal flag for this {@code ArrayProxy} instance and return a new
207 * {@code ArrayProxy} object with an not set <i>seal</i> flag but with the
208 * same underlying data structure.
209 * <p/>
210 * The <i>default</i> implementation will look like this:
211 * [code]
212 * public MyArrayProxy<T> seal() {
213 * _sealed = true;
214 * return new MyArrayProxy(_array, _start, _end);
215 * }
216 * [code]
217 *
218 * @return a new {@code ArrayProxy} instance; for command chaining.
219 */
220 public abstract ArrayProxy<T> seal();
221
222 /**
223 * Checks the given index.
224 *
225 * @param from the index to check.
226 * @throws java.lang.ArrayIndexOutOfBoundsException if the given index is
227 * not in the valid range.
228 */
229 protected final void checkIndex(final int from) {
230 if (from < 0 || from >= _length) {
231 throw new ArrayIndexOutOfBoundsException(format(
232 "Index %s is out of bounds [0, %s)", from, _length
233 ));
234 }
235 }
236
237 /**
238 * Check the given {@code from} and {@code until} indices.
239 *
240 * @param from the start index, inclusively.
241 * @param until the end index, exclusively.
242 * @throws java.lang.ArrayIndexOutOfBoundsException if the given index is
243 * not in the valid range.
244 */
245 protected final void checkIndex(final int from, final int until) {
246 if (from > until) {
247 throw new ArrayIndexOutOfBoundsException(format(
248 "fromIndex(%d) > toIndex(%d)", from, until
249 ));
250 }
251 if (from < 0 || until > _length) {
252 throw new ArrayIndexOutOfBoundsException(format(
253 "Invalid index range: [%d, %s)", from, until
254 ));
255 }
256 }
257
258
259 }
|