All Downloads are FREE. Search and download functionalities are using the official Maven repository.

aima.core.util.math.MixedRadixNumber Maven / Gradle / Ivy

Go to download

AIMA-Java Core Algorithms from the book Artificial Intelligence a Modern Approach 3rd Ed.

There is a newer version: 3.0.0
Show newest version
package aima.core.util.math;

import java.util.List;

/**
 * For details on Mixed Radix Number Representations.
 * 
 * @author Ciaran O'Reilly
 * @author Mike Stampone
 */
public class MixedRadixNumber extends Number {
	//
	private static final long serialVersionUID = 1L;
	//
	private long value = 0L;
	private long maxValue = 0L;
	private int[] radices = null;
	private int[] currentNumeralValue = null;
	private boolean recalculate = true;

	/**
	 * Constructs a mixed radix number with a specified value and a specified
	 * array of radices.
	 * 
	 * @param value
	 *            the value of the mixed radix number
	 * @param radices
	 *            the radices used to represent the value of the mixed radix
	 *            number
	 */
	public MixedRadixNumber(long value, int[] radices) {
		this.value = value;
		this.radices = new int[radices.length];
		System.arraycopy(radices, 0, this.radices, 0, radices.length);
		calculateMaxValue();
	}

	/**
	 * Constructs a mixed radix number with a specified value and a specified
	 * list of radices.
	 * 
	 * @param value
	 *            the value of the mixed radix number
	 * @param radices
	 *            the radices used to represent the value of the mixed radix
	 *            number
	 */
	public MixedRadixNumber(long value, List radices) {
		this.value = value;
		this.radices = new int[radices.size()];
		for (int i = 0; i < radices.size(); i++) {
			this.radices[i] = radices.get(i);
		}
		calculateMaxValue();
	}

	/**
	 * Constructs a mixed radix number with a specified array of numerals and a
	 * specified array of radices.
	 * 
	 * @param radixValues
	 *            the numerals of the mixed radix number
	 * @param radices
	 *            the radices of the mixed radix number
	 */
	public MixedRadixNumber(int[] radixValues, int[] radices) {
		this(0, radices);
		setCurrentValueFor(radixValues);
	}

	/**
	 * Returns the value of the mixed radix number with the specified array of
	 * numerals and the current array of radices.
	 * 
	 * @return the value of the mixed radix number
	 * 
	 * @throws IllegalArgumentException
	 *             if any of the specified numerals is less than zero, or if any
	 *             of the specified numerals is greater than it's corresponding
	 *             radix.
	 */
	public long getCurrentValueFor(int[] radixValues) {
		if (radixValues.length != radices.length) {
			throw new IllegalArgumentException(
					"Radix values not same size as Radices.");
		}

		long cvalue = 0;
		long mvalue = 1;
		for (int i = 0; i < radixValues.length; i++) {
			if (radixValues[i] < 0 || radixValues[i] >= radices[i]) {
				throw new IllegalArgumentException("Radix value " + i
						+ " is out of range for radix at this position");
			}
			if (i > 0) {
				mvalue *= radices[i - 1];
			}
			cvalue += mvalue * radixValues[i];
		}
		return cvalue;
	}

	/**
	 * Sets the value of the mixed radix number with the specified array of
	 * numerals and the current array of radices.
	 * 
	 * @param radixValues
	 *            the numerals of the mixed radix number
	 */
	public void setCurrentValueFor(int[] radixValues) {
		this.value = getCurrentValueFor(radixValues);
		System.arraycopy(radixValues, 0, this.currentNumeralValue, 0,
				radixValues.length);
		recalculate = false;
	}

	/**
	 * Returns the maximum value which can be represented by the current array
	 * of radices.
	 * 
	 * @return the maximum value which can be represented by the current array
	 *         of radices.
	 */
	public long getMaxAllowedValue() {
		return maxValue;
	}

	/**
	 * Increments the value of the mixed radix number, if the value is less than
	 * the maximum value which can be represented by the current array of
	 * radices.
	 * 
	 * @return true if the increment was successful.
	 */
	public boolean increment() {
		if (value < maxValue) {
			value++;
			recalculate = true;
			return true;
		}

		return false;
	}

	/**
	 * Decrements the value of the mixed radix number, if the value is greater
	 * than zero.
	 * 
	 * @return true if the decrement was successful.
	 */
	public boolean decrement() {
		if (value > 0) {
			value--;
			recalculate = true;
			return true;
		}
		return false;
	}

	/**
	 * Returns the numeral at the specified position.
	 * 
	 * @param atPosition
	 *            the position of the numeral to return
	 * @return the numeral at the specified position.
	 */
	public int getCurrentNumeralValue(int atPosition) {
		if (atPosition >= 0 && atPosition < radices.length) {
			if (recalculate) {
				long quotient = value;
				for (int i = 0; i < radices.length; i++) {
					if (0 != quotient) {
						currentNumeralValue[i] = (int) quotient % radices[i];
						quotient = quotient / radices[i];
					} else {
						currentNumeralValue[i] = 0;
					}

				}
				recalculate = false;
			}
			return currentNumeralValue[atPosition];
		}
		throw new IllegalArgumentException(
				"Argument atPosition must be >=0 and < " + radices.length);
	}

	//
	// START-Number
	@Override
	public int intValue() {
		return (int) longValue();
	}

	@Override
	public long longValue() {
		return value;
	}

	@Override
	public float floatValue() {
		return longValue();
	}

	@Override
	public double doubleValue() {
		return longValue();
	}

	// END-Number
	//

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < radices.length; i++) {
			sb.append("[");
			sb.append(this.getCurrentNumeralValue(i));
			sb.append("]");
		}

		return sb.toString();
	}

	//
	// PRIVATE
	//

	/**
	 * Sets the maximum value which can be represented by the current array of
	 * radices.
	 * 
	 * @throws IllegalArgumentException
	 *             if no radices are defined, if any radix is less than two, or
	 *             if the current value is greater than the maximum value which
	 *             can be represented by the current array of radices.
	 */
	private void calculateMaxValue() {
		if (0 == radices.length) {
			throw new IllegalArgumentException(
					"At least 1 radix must be defined.");
		}
		for (int i = 0; i < radices.length; i++) {
			if (radices[i] < 2) {
				throw new IllegalArgumentException(
						"Invalid radix, must be >= 2");
			}
		}

		// Calculate the maxValue allowed
		maxValue = radices[0];
		for (int i = 1; i < radices.length; i++) {
			maxValue *= radices[i];
		}
		maxValue -= 1;

		if (value > maxValue) {
			throw new IllegalArgumentException(
					"The value ["
							+ value
							+ "] cannot be represented with the radices provided, max value is "
							+ maxValue);
		}

		currentNumeralValue = new int[radices.length];
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy