RealValueRepresenter.java

Переключить прокрутку окна
Загрузить этот исходный код

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

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

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

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

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


package malik.emulator.util;

public class RealValueRepresenter extends Object
{
	public static final int MIN_ORDER_DIGITS = 2;
	public static final int MAX_ORDER_DIGITS = 4;
	public static final int FLOAT_ORDER_DIGITS = 2;
	public static final int DOUBLE_ORDER_DIGITS = 3;
	public static final int MIN_SIGNIFICAND_DIGITS = 6;
	public static final int MAX_SIGNIFICAND_DIGITS = 18;
	public static final int FLOAT_SIGNIFICAND_DIGITS = 7;
	public static final int DOUBLE_SIGNIFICAND_DIGITS = 15;

	public static double pow10(double value, int power)
	{
		if(power == Integer.MIN_VALUE)
		{
			return value * 0.d;
		}
		if(power > 0)
		{
			return value / tab_04_00(power) / tab_08_05(power) / (power >= 0x0200 ? 0.d : 1.d);
		}
		if(power < 0)
		{
			power = -power;
			return value * tab_04_00(power) * tab_08_05(power) * (power >= 0x0200 ? 0.d : 1.d);
		}
		return value;
	}

	private static double tab_04_00(int pow)
	{
		switch(pow & 0x1f)
		{
		default:
			return 0.d;
		case 0:
			return 1.d;
		case 1:
			return 1.e-001d;
		case 2:
			return 1.e-002d;
		case 3:
			return 1.e-003d;
		case 4:
			return 1.e-004d;
		case 5:
			return 1.e-005d;
		case 6:
			return 1.e-006d;
		case 7:
			return 1.e-007d;
		case 8:
			return 1.e-008d;
		case 9:
			return 1.e-009d;
		case 10:
			return 1.e-010d;
		case 11:
			return 1.e-011d;
		case 12:
			return 1.e-012d;
		case 13:
			return 1.e-013d;
		case 14:
			return 1.e-014d;
		case 15:
			return 1.e-015d;
		case 16:
			return 1.e-016d;
		case 17:
			return 1.e-017d;
		case 18:
			return 1.e-018d;
		case 19:
			return 1.e-019d;
		case 20:
			return 1.e-020d;
		case 21:
			return 1.e-021d;
		case 22:
			return 1.e-022d;
		case 23:
			return 1.e-023d;
		case 24:
			return 1.e-024d;
		case 25:
			return 1.e-025d;
		case 26:
			return 1.e-026d;
		case 27:
			return 1.e-027d;
		case 28:
			return 1.e-028d;
		case 29:
			return 1.e-029d;
		case 30:
			return 1.e-030d;
		case 31:
			return 1.e-031d;
		}
	}

	private static double tab_08_05(int pow)
	{
		switch((pow >> 5) & 0x0f)
		{
		default:
			return 0.d;
		case 0:
			return 1.d;
		case 1:
			return 1.e-032d;
		case 2:
			return 1.e-064d;
		case 3:
			return 1.e-096d;
		case 4:
			return 1.e-128d;
		case 5:
			return 1.e-160d;
		case 6:
			return 1.e-192d;
		case 7:
			return 1.e-224d;
		case 8:
			return 1.e-256d;
		case 9:
			return 1.e-288d;
		case 10:
			return 1.e-320d;
		case 11:
		case 12:
		case 13:
		case 14:
		case 15:
			return 0.d;
		}
	}


	protected final double limitValueWithFractialPart;
	protected final double limitValueWithoutExponent;
	protected final int orderDigits;
	protected final int significandDigits;
	protected final long minRepresentValue;
	protected final long maxRepresentValue;

	public RealValueRepresenter(int significandDigits, int orderDigits)
	{
		long maxRepresentValue = 1L;
		if(orderDigits < MIN_ORDER_DIGITS) orderDigits = MIN_ORDER_DIGITS;
		if(orderDigits > MAX_ORDER_DIGITS) orderDigits = MAX_ORDER_DIGITS;
		if(significandDigits < MIN_SIGNIFICAND_DIGITS) significandDigits = MIN_SIGNIFICAND_DIGITS;
		if(significandDigits > MAX_SIGNIFICAND_DIGITS) significandDigits = MAX_SIGNIFICAND_DIGITS;
		for(int i = significandDigits; i-- > 0; maxRepresentValue *= 10L);
		this.limitValueWithFractialPart = pow10(1.d, significandDigits - 1);
		this.limitValueWithoutExponent = pow10(1.d, significandDigits);
		this.orderDigits = orderDigits;
		this.significandDigits = significandDigits;
		this.minRepresentValue = maxRepresentValue / 10L;
		this.maxRepresentValue = maxRepresentValue - 1L;
	}

	public boolean equals(Object anot)
	{
		RealValueRepresenter r;
		return anot == this || anot instanceof RealValueRepresenter && orderDigits == (r = (RealValueRepresenter) anot).orderDigits && significandDigits == r.significandDigits;
	}

	public int hashCode()
	{
		return orderDigits << 8 | significandDigits;
	}

	public float parseFloat(String string) throws NumberFormatException
	{
		double result;
		if("+Infinity".equals(string) || "Infinity".equals(string))
		{
			return Float.POSITIVE_INFINITY;
		}
		if("-Infinity".equals(string))
		{
			return Float.NEGATIVE_INFINITY;
		}
		if("NaN".equals(string))
		{
			return Float.NaN;
		}
		if((result = parse(string)) < (double) -Float.MAX_VALUE || result > (double) Float.MAX_VALUE)
		{
			throw new NumberFormatException("RealValueRepresenter.parse: недопустимый формат числа.");
		}
		return (float) result;
	}

	public double parseDouble(String string) throws NumberFormatException
	{
		if("+Infinity".equals(string) || "Infinity".equals(string))
		{
			return Double.POSITIVE_INFINITY;
		}
		if("-Infinity".equals(string))
		{
			return Double.NEGATIVE_INFINITY;
		}
		if("NaN".equals(string))
		{
			return Double.NaN;
		}
		return parse(string);
	}

	public int getOrderDigits()
	{
		return orderDigits;
	}

	public int getSignificandDigits()
	{
		return significandDigits;
	}

	public String toString(double value)
	{
		boolean expform;
		char c;
		int i;
		int j;
		int len;
		int order;
		int dotpos;
		int sigdig;
		long intval;
		long tmp;
		char[] buf;
		if(value != value)
		{
			return "NaN";
		}
		if(value == Double.POSITIVE_INFINITY)
		{
			return "Infinity";
		}
		if(value == Double.NEGATIVE_INFINITY)
		{
			return "-Infinity";
		}
		len = 0;
		Array.fill(buf = new char[i = 32], 0, i, '0');
		if((intval = Double.doubleToLongBits(value)) < 0L)
		{
			buf[len++] = '-';
			value = Double.longBitsToDouble(intval &= 0x7fffffffffffffffL);
		}
		if(intval != 0L)
		{
			order = (int) (3.01029995663981195e-001d * Math.log2(value));
			sigdig = significandDigits;
			/*if(expform = value < 1.e-006d || value >= limitValueWithoutExponent)*/
			if(expform = value < 1.e-003d || value >= 1.e+007d)
			{
				if(order < 0)
				{
					order--;
				}
				if((intval = Math.round(pow10(value, sigdig - order - 1))) < minRepresentValue)
				{
					intval *= 10L;
					order--;
				}
				if(intval > maxRepresentValue)
				{
					intval /= 10L;
					order++;
				}
				dotpos = len + 1;
			}
			else if(value < 1.e+000d)
			{
				intval = Math.round(pow10(value, sigdig - 1));
				dotpos = len + 1;
			}
			else if(value < limitValueWithFractialPart)
			{
				if((intval = Math.round(pow10(value, sigdig - order - 1))) < minRepresentValue)
				{
					intval *= 10L;
					order--;
				}
				if(intval > maxRepresentValue)
				{
					intval /= 10L;
					order++;
				}
				dotpos = len + order + 1;
			}
			else
			{
				if((intval = Math.round(value)) > (tmp = maxRepresentValue))
				{
					intval = tmp;
				}
				dotpos = len + sigdig;
			}
			for(buf[dotpos] = '.', i = len + sigdig; i-- > len; )
			{
				buf[i >= dotpos ? i + 1 : i] = (char) ((int) (intval % 10L) + '0');
				intval /= 10L;
			}
			for(len += sigdig + 2; (c = buf[len - 1]) == '0' || c == '.'; )
			{
				len--;
				if(c == '.')
				{
					len += 2;
					break;
				}
			}
			if(expform)
			{
				buf[len++] = 'E';
				if(order < 0)
				{
					buf[len++] = '-';
					order = -order;
				} else
				{
					buf[len++] = '+';
				}
				for(i = j = len + orderDigits; i-- > len; )
				{
					buf[i] = (char) ((order % 10) + '0');
					order /= 10;
				}
				len = j;
			}
		} else
		{
			len += 3;
			buf[len - 2] = '.';
		}
		return new String(buf, 0, len);
	}

	protected double parse(String string) throws NumberFormatException
	{
		boolean negative;
		char c;
		double result;
		int order;
		int frac;
		int len;
		int i;
		if(string == null || (len = string.length()) <= 0)
		{
			throw new NumberFormatException("RealValueRepresenter.parse: недопустимый формат числа.");
		}
		negative = false;
		result = 0.d;
		order = 0;
		frac = 0;
		switch(string.charAt(i = 0))
		{
		default:
			break;
		case '-':
			negative = true;
			/* fall through */
		case '+':
		case ' ':
			i++;
			break;
		}
		label0:
		{
			if(i < len && ((c = string.charAt(i)) >= '0' && c <= '9' || c == '.'))
			{
				if(c == '.')
				{
					break label0;
				}
				result = (double) (c - '0');
			} else
			{
				throw new NumberFormatException("RealValueRepresenter.parse: недопустимый формат числа.");
			}
			for(i++; i < len && (c = string.charAt(i)) >= '0' && c <= '9'; i++)
			{
				result = (10.d * result) + (double) (c - '0');
			}
		}
		if(i < len && string.charAt(i) == '.')
		{
			for(i++; i < len && (c = string.charAt(i)) >= '0' && c <= '9'; frac++, i++)
			{
				result = (10.d * result) + (double) (c - '0');
			}
		}
		if(negative)
		{
			result = -result;
			negative = false;
		}
		if(i < len && ((c = string.charAt(i)) == 'E' || c == 'e'))
		{
			if(++i == len)
			{
				throw new NumberFormatException("RealValueRepresenter.parse: недопустимый формат числа.");
			}
			switch(string.charAt(i))
			{
			default:
				break;
			case '-':
				negative = true;
				/* fall through */
			case '+':
				i++;
				break;
			}
			if(i == len)
			{
				throw new NumberFormatException("RealValueRepresenter.parse: недопустимый формат числа.");
			}
			for(; i < len && (c = string.charAt(i)) >= '0' && c <= '9'; i++)
			{
				if((order = (10 * order) + (int) (c - '0')) > 9999)
				{
					throw new NumberFormatException("RealValueRepresenter.parse: недопустимый формат числа.");
				}
			}
			if(negative)
			{
				order = -order;
			}
		}
		if(i < len || Math.abs(result = pow10(result, order - frac)) > Double.MAX_VALUE)
		{
			throw new NumberFormatException("RealValueRepresenter.parse: недопустимый формат числа.");
		}
		return result;
	}
}