001/*
002 * Java Genetic Algorithm Library (jenetics-8.0.0).
003 * Copyright (c) 2007-2024 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.internal.collection;
021
022import static java.lang.Math.min;
023import static java.lang.String.format;
024
025import java.io.Serial;
026import java.util.Comparator;
027import java.util.Iterator;
028import java.util.ListIterator;
029import java.util.function.Function;
030import java.util.function.Supplier;
031import java.util.random.RandomGenerator;
032
033import io.jenetics.util.ISeq;
034import io.jenetics.util.MSeq;
035
036/**
037 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
038 * @since 1.4
039 * @version 3.4
040 */
041public class ArrayMSeq<T> extends ArraySeq<T> implements MSeq<T> {
042
043        @Serial
044        private static final long serialVersionUID = 1L;
045
046        public ArrayMSeq(final Array<T> array) {
047                super(array);
048        }
049
050        @Override
051        public MSeq<T> copy() {
052                return isEmpty()
053                        ? this
054                        : new ArrayMSeq<>(array.copy());
055        }
056
057        @Override
058        public Iterator<T> iterator() {
059                return listIterator();
060        }
061
062        @Override
063        public ListIterator<T> listIterator() {
064                return new BaseMSeqIterator<>(array);
065        }
066
067        @Override
068        public void set(final int index, final T value) {
069                array.set(index, value);
070        }
071
072        @Override
073        public MSeq<T> setAll(final Iterator<? extends T> it) {
074                for (int i = 0; i < array.length() && it.hasNext(); ++i) {
075                        array.set(i, it.next());
076                }
077                return this;
078        }
079
080        @Override
081        public MSeq<T> setAll(final Iterable<? extends T> values) {
082                return setAll(values.iterator());
083        }
084
085        @Override
086        public MSeq<T> setAll(final T[] values) {
087                for (int i = 0, n = min(array.length(), values.length); i < n; ++i) {
088                        array.set(i, values[i]);
089                }
090                return this;
091        }
092
093        public MSeq<T> fill(final Supplier<? extends T> supplier) {
094                for (int i = 0; i < array.length(); ++i) {
095                        array.set(i, supplier.get());
096                }
097                return this;
098        }
099
100        @Override
101        public ArrayMSeq<T> sort(
102                final int start,
103                final int end,
104                final Comparator<? super T> comparator
105        ) {
106                array.sort(start, end, comparator);
107                return this;
108        }
109
110        @Override
111        public MSeq<T> shuffle(final RandomGenerator random) {
112                for (int j = length() - 1; j > 0; --j) {
113                        swap(j, random.nextInt(j + 1));
114                }
115                return this;
116        }
117
118        @Override
119        public void swap(final int i, final int j) {
120                final T temp = array.get(i);
121                array.set(i, array.get(j));
122                array.set(j, temp);
123        }
124
125        @Override
126        public void swap(int start, int end, MSeq<T> other, int otherStart) {
127                checkIndex(start, end, otherStart, other.length());
128
129                if (start < end) {
130                        for (int i = end - start; --i >= 0;) {
131                                final T temp = array.get(i + start);
132                                array.set(i + start, other.get(otherStart + i));
133                                other.set(otherStart + i, temp);
134                        }
135                }
136        }
137
138        protected void checkIndex(
139                final int start, final int end,
140                final int otherStart, final int otherLength
141        ) {
142                array.checkIndex(start, end);
143                if (otherStart < 0 || (otherStart + (end - start)) > otherLength) {
144                        throw new ArrayIndexOutOfBoundsException(format(
145                                "Invalid index range: [%d, %d)",
146                                otherStart, otherStart + end - start
147                        ));
148                }
149        }
150
151        @Override
152        public MSeq<T> subSeq(final int start, final int end) {
153                if (start > end) {
154                        throw new ArrayIndexOutOfBoundsException(format(
155                                "start[%d] > end[%d]", start, end
156                        ));
157                }
158                if (start < 0 || end > length()) {
159                        throw new ArrayIndexOutOfBoundsException(format(
160                                "Indexes (%d, %d) range: [%d..%d)", start, end, 0, length()
161                        ));
162                }
163
164                return start == end
165                        ? Empty.mseq()
166                        : new ArrayMSeq<>(array.slice(start, end));
167        }
168
169        @Override
170        public MSeq<T> subSeq(final int start) {
171                if (start < 0 || start > length()) {
172                        throw new ArrayIndexOutOfBoundsException(format(
173                                "Index %d range: [%d..%d)", start, 0, length()
174                        ));
175                }
176
177                return start == length()
178                        ? Empty.mseq()
179                        : new ArrayMSeq<>(array.slice(start, length()));
180        }
181
182        @Override
183        public <B> MSeq<B> map(final Function<? super T, ? extends B> mapper) {
184                final Array<B> mapped = Array.ofLength(length());
185                for (int i = 0; i < length(); ++i) {
186                        mapped.set(i, mapper.apply(array.get(i)));
187                }
188                return new ArrayMSeq<>(mapped);
189        }
190
191        @Override
192        public MSeq<T> append(final Iterable<? extends T> values) {
193                return new ArrayMSeq<>(__append(values));
194        }
195
196        @Override
197        public MSeq<T> prepend(final Iterable<? extends T> values) {
198                return new ArrayMSeq<>(__prepend(values));
199        }
200
201        @Override
202        public ISeq<T> toISeq() {
203                return isEmpty()
204                        ? Empty.iseq()
205                        : new ArrayISeq<>(array.seal());
206        }
207
208}