package aalg.algebra;

/**
 * Base implementation of field.
 * @author Ing. Petr Ležák
 *
 * @param <T> type of field element
 */
public abstract class FieldImpl<T extends IElement> implements IField<T> {
	public abstract T add (final T a, final T b);
	public abstract T multiply (final T a, final T b);
	public abstract T additiveInverse (final T x);
	public abstract T multiplicativeInverse (final T x);
	public abstract T getAdditiveIdentity();
	public abstract T getMultiplicativeIdentity();
	
	/**
	 * Calculates division as multiplication by multiplicative inverse element.
	 * Children may implement more effective division but with same behavior.
	 * @param a numerator
	 * @param b denominator
	 * @return a / b
	 */
	public T divide (final T a, final T b) {
		return multiply (a, multiplicativeInverse(b));
	}

	/**
	 * Calculates subtraction as addition of additive inverse element.
	 * Children may implement more effective subtraction but with same behavior.
	 * @param a element
	 * @param b element
	 * @return a - b
	 */	
	public T subtract (final T a, final T b) {
		return add (a, additiveInverse(b));
	}
	
	/**
	 * Returns additive group of the field.
	 * This group contains all element of the field with operation addition.
	 * @return additive group of the field
	 */
	public IGroup<T> getAdditiveGroup() {
		return new AdditiveFieldGroup<T>(this);
	}

	/**
	 * Returns multiplicative group of the field.
	 * This group contains all element of the field except additive identity (zero)
	 * with operation multiplication.
	 * @return multiplicative group of the field
	 */
	public IGroup<T> getMultiplicativeGroup() {
		return new MultiplicativeFieldGroup<T>(this);
	}

}
