/*
	Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
	и других спецификаций для функционирования компактных приложений на языке
	Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

	Copyright © 2016, 2019 Малик Разработчик

	Это свободная программа: вы можете перераспространять ее и/или изменять
	ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
	в каком она была опубликована Фондом свободного программного обеспечения;
	либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

	Эта программа распространяется в надежде, что она будет полезной,
	но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
	или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
	общественной лицензии GNU.

	Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
	вместе с этой программой. Если это не так, см.
	<https://www.gnu.org/licenses/>.
*/


package java.lang;

import malik.emulator.util.*;

public final class Array extends Object
{
	public static void copy(boolean[] src, int srcOffset, boolean[] dst, int dstOffset, int length)
	{
		int esi;
		int edi;
		int len;
		int srcLimit;
		int dstLimit;
		if(length <= 0)
		{
			return;
		}
		if(src == null)
		{
			throw new NullPointerException("Array.copy: аргумент src равен нулевой ссылке.");
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.copy: аргумент dst равен нулевой ссылке.");
		}
		if((srcLimit = srcOffset + length) > (len = src.length) || srcLimit < srcOffset || srcOffset > len || srcOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		if((dstLimit = dstOffset + length) > (len = dst.length) || dstLimit < dstOffset || dstOffset > len || dstOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		esi = getFirstElementAddress(src) + (srcOffset);
		edi = getFirstElementAddress(dst) + (dstOffset);
		if(esi < edi)
		{
			MalikSystem.arraycopyb_byte(src, srcLimit, dst, dstLimit, length);
			return;
		}
		MalikSystem.arraycopyf_byte(src, srcOffset, dst, dstOffset, length);
	}

	public static void copy(char[] src, int srcOffset, char[] dst, int dstOffset, int length)
	{
		int esi;
		int edi;
		int len;
		int srcLimit;
		int dstLimit;
		if(length <= 0)
		{
			return;
		}
		if(src == null)
		{
			throw new NullPointerException("Array.copy: аргумент src равен нулевой ссылке.");
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.copy: аргумент dst равен нулевой ссылке.");
		}
		if((srcLimit = srcOffset + length) > (len = src.length) || srcLimit < srcOffset || srcOffset > len || srcOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		if((dstLimit = dstOffset + length) > (len = dst.length) || dstLimit < dstOffset || dstOffset > len || dstOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		esi = getFirstElementAddress(src) + (srcOffset << 1);
		edi = getFirstElementAddress(dst) + (dstOffset << 1);
		if(esi < edi)
		{
			MalikSystem.arraycopyb_short(src, srcLimit, dst, dstLimit, length);
			return;
		}
		MalikSystem.arraycopyf_short(src, srcOffset, dst, dstOffset, length);
	}

	public static void copy(float[] src, int srcOffset, float[] dst, int dstOffset, int length)
	{
		int esi;
		int edi;
		int len;
		int srcLimit;
		int dstLimit;
		if(length <= 0)
		{
			return;
		}
		if(src == null)
		{
			throw new NullPointerException("Array.copy: аргумент src равен нулевой ссылке.");
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.copy: аргумент dst равен нулевой ссылке.");
		}
		if((srcLimit = srcOffset + length) > (len = src.length) || srcLimit < srcOffset || srcOffset > len || srcOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		if((dstLimit = dstOffset + length) > (len = dst.length) || dstLimit < dstOffset || dstOffset > len || dstOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		esi = getFirstElementAddress(src) + (srcOffset << 2);
		edi = getFirstElementAddress(dst) + (dstOffset << 2);
		if(esi < edi)
		{
			MalikSystem.arraycopyb_int(src, srcLimit, dst, dstLimit, length);
			return;
		}
		MalikSystem.arraycopyf_int(src, srcOffset, dst, dstOffset, length);
	}

	public static void copy(double[] src, int srcOffset, double[] dst, int dstOffset, int length)
	{
		int esi;
		int edi;
		int len;
		int srcLimit;
		int dstLimit;
		if(length <= 0)
		{
			return;
		}
		if(src == null)
		{
			throw new NullPointerException("Array.copy: аргумент src равен нулевой ссылке.");
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.copy: аргумент dst равен нулевой ссылке.");
		}
		if((srcLimit = srcOffset + length) > (len = src.length) || srcLimit < srcOffset || srcOffset > len || srcOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		if((dstLimit = dstOffset + length) > (len = dst.length) || dstLimit < dstOffset || dstOffset > len || dstOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		esi = getFirstElementAddress(src) + (srcOffset << 3);
		edi = getFirstElementAddress(dst) + (dstOffset << 3);
		if(esi < edi)
		{
			MalikSystem.arraycopyb_long(src, srcLimit, dst, dstLimit, length);
			return;
		}
		MalikSystem.arraycopyf_long(src, srcOffset, dst, dstOffset, length);
	}

	public static void copy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int length)
	{
		int esi;
		int edi;
		int len;
		int srcLimit;
		int dstLimit;
		if(length <= 0)
		{
			return;
		}
		if(src == null)
		{
			throw new NullPointerException("Array.copy: аргумент src равен нулевой ссылке.");
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.copy: аргумент dst равен нулевой ссылке.");
		}
		if((srcLimit = srcOffset + length) > (len = src.length) || srcLimit < srcOffset || srcOffset > len || srcOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		if((dstLimit = dstOffset + length) > (len = dst.length) || dstLimit < dstOffset || dstOffset > len || dstOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		esi = getFirstElementAddress(src) + (srcOffset);
		edi = getFirstElementAddress(dst) + (dstOffset);
		if(esi < edi)
		{
			MalikSystem.arraycopyb_byte(src, srcLimit, dst, dstLimit, length);
			return;
		}
		MalikSystem.arraycopyf_byte(src, srcOffset, dst, dstOffset, length);
	}

	public static void copy(short[] src, int srcOffset, short[] dst, int dstOffset, int length)
	{
		int esi;
		int edi;
		int len;
		int srcLimit;
		int dstLimit;
		if(length <= 0)
		{
			return;
		}
		if(src == null)
		{
			throw new NullPointerException("Array.copy: аргумент src равен нулевой ссылке.");
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.copy: аргумент dst равен нулевой ссылке.");
		}
		if((srcLimit = srcOffset + length) > (len = src.length) || srcLimit < srcOffset || srcOffset > len || srcOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		if((dstLimit = dstOffset + length) > (len = dst.length) || dstLimit < dstOffset || dstOffset > len || dstOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		esi = getFirstElementAddress(src) + (srcOffset << 1);
		edi = getFirstElementAddress(dst) + (dstOffset << 1);
		if(esi < edi)
		{
			MalikSystem.arraycopyb_short(src, srcLimit, dst, dstLimit, length);
			return;
		}
		MalikSystem.arraycopyf_short(src, srcOffset, dst, dstOffset, length);
	}

	public static void copy(int[] src, int srcOffset, int[] dst, int dstOffset, int length)
	{
		int esi;
		int edi;
		int len;
		int srcLimit;
		int dstLimit;
		if(length <= 0)
		{
			return;
		}
		if(src == null)
		{
			throw new NullPointerException("Array.copy: аргумент src равен нулевой ссылке.");
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.copy: аргумент dst равен нулевой ссылке.");
		}
		if((srcLimit = srcOffset + length) > (len = src.length) || srcLimit < srcOffset || srcOffset > len || srcOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		if((dstLimit = dstOffset + length) > (len = dst.length) || dstLimit < dstOffset || dstOffset > len || dstOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		esi = getFirstElementAddress(src) + (srcOffset << 2);
		edi = getFirstElementAddress(dst) + (dstOffset << 2);
		if(esi < edi)
		{
			MalikSystem.arraycopyb_int(src, srcLimit, dst, dstLimit, length);
			return;
		}
		MalikSystem.arraycopyf_int(src, srcOffset, dst, dstOffset, length);
	}

	public static void copy(long[] src, int srcOffset, long[] dst, int dstOffset, int length)
	{
		int esi;
		int edi;
		int len;
		int srcLimit;
		int dstLimit;
		if(length <= 0)
		{
			return;
		}
		if(src == null)
		{
			throw new NullPointerException("Array.copy: аргумент src равен нулевой ссылке.");
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.copy: аргумент dst равен нулевой ссылке.");
		}
		if((srcLimit = srcOffset + length) > (len = src.length) || srcLimit < srcOffset || srcOffset > len || srcOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		if((dstLimit = dstOffset + length) > (len = dst.length) || dstLimit < dstOffset || dstOffset > len || dstOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		esi = getFirstElementAddress(src) + (srcOffset << 3);
		edi = getFirstElementAddress(dst) + (dstOffset << 3);
		if(esi < edi)
		{
			MalikSystem.arraycopyb_long(src, srcLimit, dst, dstLimit, length);
			return;
		}
		MalikSystem.arraycopyf_long(src, srcOffset, dst, dstOffset, length);
	}

	public static void copy(Object[] src, int srcOffset, Object[] dst, int dstOffset, int length)
	{
		int esi;
		int edi;
		int len;
		int srcLimit;
		int dstLimit;
		Class srcType;
		Class dstType;
		if(length <= 0)
		{
			return;
		}
		if(src == null)
		{
			throw new NullPointerException("Array.copy: аргумент src равен нулевой ссылке.");
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.copy: аргумент dst равен нулевой ссылке.");
		}
		if((srcLimit = srcOffset + length) > (len = src.length) || srcLimit < srcOffset || srcOffset > len || srcOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		if((dstLimit = dstOffset + length) > (len = dst.length) || dstLimit < dstOffset || dstOffset > len || dstOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copy: индекс выходит из диапазона.");
		}
		if(!(dstType = dst.getClass().componentType).isAssignableFrom(srcType = src.getClass().componentType))
		{
			throw new ArrayStoreException("Array.copy", dstType, srcType, false);
		}
		esi = getFirstElementAddress(src) + (srcOffset << 2);
		edi = getFirstElementAddress(dst) + (dstOffset << 2);
		if(esi < edi)
		{
			MalikSystem.arraycopyb_object(src, srcLimit, dst, dstLimit, length);
			return;
		}
		MalikSystem.arraycopyf_object(src, srcOffset, dst, dstOffset, length);
	}

	public static void copyReferences(Object[] src, int srcOffset, Object[] dst, int dstOffset, int length)
	{
		int esi;
		int edi;
		int lim;
		int len;
		if(length <= 0)
		{
			return;
		}
		if(src == null)
		{
			throw new NullPointerException("Array.copyReferences: аргумент src равен нулевой ссылке.");
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.copyReferences: аргумент dst равен нулевой ссылке.");
		}
		if((lim = srcOffset + length) > (len = src.length) || lim < srcOffset || srcOffset > len || srcOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copyReferences: индекс выходит из диапазона.");
		}
		if((lim = dstOffset + length) > (len = dst.length) || lim < dstOffset || dstOffset > len || dstOffset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.copyReferences: индекс выходит из диапазона.");
		}
		esi = getFirstElementAddress(src) + (srcOffset << 2);
		edi = getFirstElementAddress(dst) + (dstOffset << 2);
		if(esi >= edi)
		{
			for(; length-- > 0; dst[dstOffset++] = src[srcOffset++]);
			return;
		}
		for(srcOffset += length, dstOffset += length; length-- > 0; dst[--dstOffset] = src[--srcOffset]);
	}

	public static void fill(boolean[] dst, int offset, int length, boolean value)
	{
		int lim;
		int len;
		if(length <= 0)
		{
			return;
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.fill: аргумент dst равен нулевой ссылке.");
		}
		if((lim = offset + length) > (len = dst.length) || lim < offset || offset > len || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.fill: индекс выходит из диапазона.");
		}
		MalikSystem.arrayfill_byte(dst, offset, length, value ? 1 : 0);
	}

	public static void fill(char[] dst, int offset, int length, int value)
	{
		int lim;
		int len;
		if(length <= 0)
		{
			return;
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.fill: аргумент dst равен нулевой ссылке.");
		}
		if((lim = offset + length) > (len = dst.length) || lim < offset || offset > len || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.fill: индекс выходит из диапазона.");
		}
		MalikSystem.arrayfill_short(dst, offset, length, value);
	}

	public static void fill(float[] dst, int offset, int length, float value)
	{
		int lim;
		int len;
		if(length <= 0)
		{
			return;
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.fill: аргумент dst равен нулевой ссылке.");
		}
		if((lim = offset + length) > (len = dst.length) || lim < offset || offset > len || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.fill: индекс выходит из диапазона.");
		}
		MalikSystem.arrayfill_int(dst, offset, length, Float.floatToIntBits(value));
	}

	public static void fill(double[] dst, int offset, int length, double value)
	{
		int lim;
		int len;
		if(length <= 0)
		{
			return;
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.fill: аргумент dst равен нулевой ссылке.");
		}
		if((lim = offset + length) > (len = dst.length) || lim < offset || offset > len || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.fill: индекс выходит из диапазона.");
		}
		MalikSystem.arrayfill_long(dst, offset, length, Double.doubleToLongBits(value));
	}

	public static void fill(byte[] dst, int offset, int length, int value)
	{
		int lim;
		int len;
		if(length <= 0)
		{
			return;
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.fill: аргумент dst равен нулевой ссылке.");
		}
		if((lim = offset + length) > (len = dst.length) || lim < offset || offset > len || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.fill: индекс выходит из диапазона.");
		}
		MalikSystem.arrayfill_byte(dst, offset, length, value);
	}

	public static void fill(short[] dst, int offset, int length, int value)
	{
		int lim;
		int len;
		if(length <= 0)
		{
			return;
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.fill: аргумент dst равен нулевой ссылке.");
		}
		if((lim = offset + length) > (len = dst.length) || lim < offset || offset > len || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.fill: индекс выходит из диапазона.");
		}
		MalikSystem.arrayfill_short(dst, offset, length, value);
	}

	public static void fill(int[] dst, int offset, int length, int value)
	{
		int lim;
		int len;
		if(length <= 0)
		{
			return;
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.fill: аргумент dst равен нулевой ссылке.");
		}
		if((lim = offset + length) > (len = dst.length) || lim < offset || offset > len || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.fill: индекс выходит из диапазона.");
		}
		MalikSystem.arrayfill_int(dst, offset, length, value);
	}

	public static void fill(long[] dst, int offset, int length, long value)
	{
		int lim;
		int len;
		if(length <= 0)
		{
			return;
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.fill: аргумент dst равен нулевой ссылке.");
		}
		if((lim = offset + length) > (len = dst.length) || lim < offset || offset > len || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.fill: индекс выходит из диапазона.");
		}
		MalikSystem.arrayfill_long(dst, offset, length, value);
	}

	public static void fill(Object[] dst, int offset, int length, Object value)
	{
		int lim;
		int len;
		Class srcType;
		Class dstType;
		if(length <= 0)
		{
			return;
		}
		if(dst == null)
		{
			throw new NullPointerException("Array.fill: аргумент dst равен нулевой ссылке.");
		}
		if((lim = offset + length) > (len = dst.length) || lim < offset || offset > len || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException("Array.fill: индекс выходит из диапазона.");
		}
		if(value != null && !(dstType = dst.getClass().componentType).isAssignableFrom(srcType = value.getClass()))
		{
			throw new ArrayStoreException("Array.fill", dstType, srcType, false);
		}
		MalikSystem.arrayfill_object(dst, offset, length, value);
	}

	public static void checkIndex(String method, int arrayLength, int index) throws ArrayIndexOutOfBoundsException
	{
		if(index < 0 || index >= arrayLength)
		{
			throw new ArrayIndexOutOfBoundsException((new StringBuilder()).append(method != null ? method.concat(": индекс ") : "Индекс ").append(index).append(" выходит из диапазона.").toString(), true);
		}
	}

	public static void checkBound(String method, int arrayLength, int offset, int length) throws ArrayIndexOutOfBoundsException
	{
		int lim;
		if((lim = offset + length) > arrayLength || lim < offset || offset > arrayLength || offset < 0)
		{
			throw new ArrayIndexOutOfBoundsException(method != null ? method.concat(": индекс выходит из диапазона.") : "Индекс выходит из диапазона.", true);
		}
	}

	public static boolean isBoundValid(int objectLength, int offset, int length)
	{
		int lim;
		return (lim = offset + length) <= objectLength && lim >= offset && offset <= objectLength && offset >= 0;
	}

	public static int findf(boolean[] src, int startFromIndex, boolean value)
	{
		if(startFromIndex < 0) startFromIndex = 0;
		if(startFromIndex >= (src == null ? 0 : src.length)) return startFromIndex;
		return MalikSystem.arrayfindf_byte(src, startFromIndex, value ? 1 : 0);
	}

	public static int findf(char[] src, int startFromIndex, int value)
	{
		if(startFromIndex < 0) startFromIndex = 0;
		if(startFromIndex >= (src == null ? 0 : src.length)) return startFromIndex;
		return MalikSystem.arrayfindf_short(src, startFromIndex, value);
	}

	public static int findf(float[] src, int startFromIndex, float value)
	{
		if(startFromIndex < 0) startFromIndex = 0;
		if(startFromIndex >= (src == null ? 0 : src.length)) return startFromIndex;
		return MalikSystem.arrayfindf_float(src, startFromIndex, value);
	}

	public static int findf(double[] src, int startFromIndex, double value)
	{
		if(startFromIndex < 0) startFromIndex = 0;
		if(startFromIndex >= (src == null ? 0 : src.length)) return startFromIndex;
		return MalikSystem.arrayfindf_double(src, startFromIndex, value);
	}

	public static int findf(byte[] src, int startFromIndex, int value)
	{
		if(startFromIndex < 0) startFromIndex = 0;
		if(startFromIndex >= (src == null ? 0 : src.length)) return startFromIndex;
		return MalikSystem.arrayfindf_byte(src, startFromIndex, value);
	}

	public static int findf(short[] src, int startFromIndex, int value)
	{
		if(startFromIndex < 0) startFromIndex = 0;
		if(startFromIndex >= (src == null ? 0 : src.length)) return startFromIndex;
		return MalikSystem.arrayfindf_short(src, startFromIndex, value);
	}

	public static int findf(int[] src, int startFromIndex, int value)
	{
		if(startFromIndex < 0) startFromIndex = 0;
		if(startFromIndex >= (src == null ? 0 : src.length)) return startFromIndex;
		return MalikSystem.arrayfindf_int(src, startFromIndex, value);
	}

	public static int findf(long[] src, int startFromIndex, long value)
	{
		if(startFromIndex < 0) startFromIndex = 0;
		if(startFromIndex >= (src == null ? 0 : src.length)) return startFromIndex;
		return MalikSystem.arrayfindf_long(src, startFromIndex, value);
	}

	public static int findf(Object[] src, int startFromIndex, Object value)
	{
		if(startFromIndex < 0) startFromIndex = 0;
		if(startFromIndex >= (src == null ? 0 : src.length)) return startFromIndex;
		return MalikSystem.arrayfindf_object(src, startFromIndex, value);
	}

	public static int findb(boolean[] src, int startFromIndex, boolean value)
	{
		int len;
		if(startFromIndex >= (len = src == null ? 0 : src.length)) startFromIndex = len - 1;
		return startFromIndex < 0 ? startFromIndex : MalikSystem.arrayfindb_byte(src, startFromIndex, value ? 1 : 0);
	}

	public static int findb(char[] src, int startFromIndex, int value)
	{
		int len;
		if(startFromIndex >= (len = src == null ? 0 : src.length)) startFromIndex = len - 1;
		return startFromIndex < 0 ? startFromIndex : MalikSystem.arrayfindb_short(src, startFromIndex, value);
	}

	public static int findb(float[] src, int startFromIndex, float value)
	{
		int len;
		if(startFromIndex >= (len = src == null ? 0 : src.length)) startFromIndex = len - 1;
		return startFromIndex < 0 ? startFromIndex : MalikSystem.arrayfindb_float(src, startFromIndex, value);
	}

	public static int findb(double[] src, int startFromIndex, double value)
	{
		int len;
		if(startFromIndex >= (len = src == null ? 0 : src.length)) startFromIndex = len - 1;
		return startFromIndex < 0 ? startFromIndex : MalikSystem.arrayfindb_double(src, startFromIndex, value);
	}

	public static int findb(byte[] src, int startFromIndex, int value)
	{
		int len;
		if(startFromIndex >= (len = src == null ? 0 : src.length)) startFromIndex = len - 1;
		return startFromIndex < 0 ? startFromIndex : MalikSystem.arrayfindb_byte(src, startFromIndex, value);
	}

	public static int findb(short[] src, int startFromIndex, int value)
	{
		int len;
		if(startFromIndex >= (len = src == null ? 0 : src.length)) startFromIndex = len - 1;
		return startFromIndex < 0 ? startFromIndex : MalikSystem.arrayfindb_short(src, startFromIndex, value);
	}

	public static int findb(int[] src, int startFromIndex, int value)
	{
		int len;
		if(startFromIndex >= (len = src == null ? 0 : src.length)) startFromIndex = len - 1;
		return startFromIndex < 0 ? startFromIndex : MalikSystem.arrayfindb_int(src, startFromIndex, value);
	}

	public static int findb(long[] src, int startFromIndex, long value)
	{
		int len;
		if(startFromIndex >= (len = src == null ? 0 : src.length)) startFromIndex = len - 1;
		return startFromIndex < 0 ? startFromIndex : MalikSystem.arrayfindb_long(src, startFromIndex, value);
	}

	public static int findb(Object[] src, int startFromIndex, Object value)
	{
		int len;
		if(startFromIndex >= (len = src == null ? 0 : src.length)) startFromIndex = len - 1;
		return startFromIndex < 0 ? startFromIndex : MalikSystem.arrayfindb_object(src, startFromIndex, value);
	}

	public static int getFirstElementAddress(Object array)
	{
		if(array == null)
		{
			throw new NullPointerException("Array.getFirstElementAddress: аргумент array равен нулевой ссылке.");
		}
		if(!array.getClass().isArray())
		{
			throw new IllegalArgumentException("Array.getFirstElementAddress: аргумент array не является массивом.");
		}
		return array.getArrayAddress();
	}

	public static int getFirstElementAddress(String string)
	{
		if(string == null)
		{
			throw new NullPointerException("Array.getFirstElementAddress: аргумент string равен нулевой ссылке.");
		}
		return string.getCharsAddress();
	}

	public static long intersectBound(int objectLength, int offset, int length)
	{
		int limit;
		int beginIndex = offset < 0 ? 0 : offset > objectLength ? objectLength : offset;
		int endIndex = (limit = offset + length) < 0 ? 0 : limit > objectLength ? objectLength : limit;
		return beginIndex > endIndex ? (long) endIndex : (long) beginIndex | (long) (endIndex - beginIndex) << 32;
	}

	public static byte[] createSystemByteArray(int address, int arrayLength)
	{
		int ref;
		byte[] result;
		if(arrayLength < 0)
		{
			throw new NegativeArraySizeException("Array.createSystemByteArray: длина массива не может быть отрицательной.");
		}
		Memory.checkSize(((long) arrayLength) + 0x10L);
		if(Memory.isHeapAddress(address, address + (arrayLength)))
		{
			throw new IllegalArgumentException("Array.createSystemByteArray: диапазон адресов, занимаемых массивом, не может пересекаться с кучей.");
		}
		result = (byte[]) Memory.allocateInstanceOf(MalikSystem.getClassInstance("[B"), 0x10, arrayLength);
		MalikSystem.setIntAt((ref = MalikSystem.convertToReference(result)) + 0x0c, address - ref - 0x10);
		return result;
	}

	public static short[] createSystemShortArray(int address, int arrayLength)
	{
		int ref;
		short[] result;
		if(arrayLength < 0)
		{
			throw new NegativeArraySizeException("Array.createSystemShortArray: длина массива не может быть отрицательной.");
		}
		Memory.checkSize(((long) arrayLength << 1) + 0x10L);
		if(Memory.isHeapAddress(address, address + (arrayLength << 1)))
		{
			throw new IllegalArgumentException("Array.createSystemShortArray: диапазон адресов, занимаемых массивом, не может пересекаться с кучей.");
		}
		result = (short[]) Memory.allocateInstanceOf(MalikSystem.getClassInstance("[S"), 0x10, arrayLength);
		MalikSystem.setIntAt((ref = MalikSystem.convertToReference(result)) + 0x0c, address - ref - 0x10);
		return result;
	}

	public static int[] createSystemIntArray(int address, int arrayLength)
	{
		int ref;
		int[] result;
		if(arrayLength < 0)
		{
			throw new NegativeArraySizeException("Array.createSystemIntArray: длина массива не может быть отрицательной.");
		}
		Memory.checkSize(((long) arrayLength << 2) + 0x10L);
		if(Memory.isHeapAddress(address, address + (arrayLength << 2)))
		{
			throw new IllegalArgumentException("Array.createSystemIntArray: диапазон адресов, занимаемых массивом, не может пересекаться с кучей.");
		}
		result = (int[]) Memory.allocateInstanceOf(MalikSystem.getClassInstance("[I"), 0x10, arrayLength);
		MalikSystem.setIntAt((ref = MalikSystem.convertToReference(result)) + 0x0c, address - ref - 0x10);
		return result;
	}

	public static long[] createSystemLongArray(int address, int arrayLength)
	{
		int ref;
		long[] result;
		if(arrayLength < 0)
		{
			throw new NegativeArraySizeException("Array.createSystemLongArray: длина массива не может быть отрицательной.");
		}
		Memory.checkSize(((long) arrayLength << 3) + 0x10L);
		if(Memory.isHeapAddress(address, address + (arrayLength << 3)))
		{
			throw new IllegalArgumentException("Array.createSystemLongArray: диапазон адресов, занимаемых массивом, не может пересекаться с кучей.");
		}
		result = (long[]) Memory.allocateInstanceOf(MalikSystem.getClassInstance("[J"), 0x10, arrayLength);
		MalikSystem.setIntAt((ref = MalikSystem.convertToReference(result)) + 0x0c, address - ref - 0x10);
		return result;
	}

	public static Object create(int arrayLength, Class arrayType)
	{
		long refSize;
		Class arrayComponentType;
		if(arrayType == null)
		{
			throw new NullPointerException("Array.create: аргумент arrayType равен нулевой ссылке.");
		}
		if((arrayComponentType = arrayType.componentType) == null)
		{
			throw new IllegalArgumentException("Array.create: аргумент arrayType не является классом массива.");
		}
		if(arrayLength < 0)
		{
			throw new NegativeArraySizeException("Array.create: длина массива не может быть отрицательной.");
		}
		label0:
		{
			if(arrayComponentType == MalikSystem.getClassInstance("Z") || arrayComponentType == MalikSystem.getClassInstance("B"))
			{
				refSize = (long) arrayLength;
				break label0;
			}
			if(arrayComponentType == MalikSystem.getClassInstance("C") || arrayComponentType == MalikSystem.getClassInstance("S"))
			{
				refSize = (long) arrayLength << 1;
				break label0;
			}
			if(arrayComponentType == MalikSystem.getClassInstance("F") || arrayComponentType == MalikSystem.getClassInstance("I"))
			{
				refSize = (long) arrayLength << 2;
				break label0;
			}
			if(arrayComponentType == MalikSystem.getClassInstance("D") || arrayComponentType == MalikSystem.getClassInstance("J"))
			{
				refSize = (long) arrayLength << 3;
				break label0;
			}
			refSize = (long) arrayLength << 2;
		}
		Memory.checkSize(refSize += 0x10L);
		return Memory.allocateInstanceOf(arrayType, (int) refSize, arrayLength);
	}

	public static Object create(int[] arrayLengths, Class arrayType)
	{
		int i;
		int len;
		int[] dim;
		if(arrayType == null)
		{
			throw new NullPointerException("Array.create: аргумент arrayType равен нулевой ссылке.");
		}
		if(!arrayType.isArray())
		{
			throw new IllegalArgumentException("Array.create: аргумент arrayType не является классом массива.");
		}
		if(arrayType.getArrayDimensionsQuantity() < (len = arrayLengths == null ? 0 : arrayLengths.length))
		{
			throw new IllegalArgumentException("Array.create: количество измерений массива не соответствует требуемому.");
		}
		if(len <= 0)
		{
			throw new IllegalArgumentException("Array.create: количество измерений массива не может быть нулевым.");
		}
		for(MalikSystem.arraycopyf_int(arrayLengths, 0, dim = new int[len], 0, len), i = len; i-- > 0; )
		{
			if(dim[i] < 0)
			{
				throw new NegativeArraySizeException("Array.create: длина массива не может быть отрицательной.");
			}
		}
		return len > 1 ? createSubArray(dim, len, arrayType) : create(dim[0], arrayType);
	}

	private static Object createSubArray(int[] dim, int dimCount, Class arrayType)
	{
		int len;
		Object[] result;
		Class component;
		if(dimCount == 1)
		{
			return create(dim[dim.length - 1], arrayType);
		}
		result = (Object[]) create(len = dim[dim.length - dimCount--], arrayType);
		component = arrayType.componentType;
		for(int i = len; i-- > 0; )
		{
			result[i] = createSubArray(dim, dimCount, component);
		}
		return result;
	}


	private Array()
	{
	}
}
