package aalg.algebra;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;

/**
 * Multiplicative group over given field.
 * @author Ing. Petr Ležák
 *
 * @param <T> type of element
 */
public class MultiplicativeFieldGroup<T extends IElement> extends GroupImpl<T> {

	private final IField<T> field;
	
	/**
	 * Creates group over given field.
	 * @param field underlying field
	 */
	public MultiplicativeFieldGroup(final IField<T> field) {
		this.field = field;
	}
	
	@Override
	public T operation(final T a, final T b) {
		return field.multiply(a, b);
	}

	@Override
	public T getIdentity() {
		return field.getMultiplicativeIdentity();
	}
	
	@Override
	public T getInverse(final T x) {
		return field.multiplicativeInverse(x);
	}

	@Override
	public T readElement(final InputStream stream) throws IOException {
		return field.readElement(stream);
	}

	@Override
	public void writeElement(final T element, final OutputStream stream) throws IOException {
		field.writeElement(element, stream);
	}

	@Override
	public boolean containsElement (final T element) {
		return field.containsElement(element) && !element.equals(field.getAdditiveIdentity());
	}

	@Override
	public Iterable<T> getElements() {
		return new FilteringIterable<T>(field.getElements(), this);
	}

	@Override
	public BigInteger getOrder() {
		return field.getOrder().subtract(BigInteger.ONE);
	}
	
	@Override
	public T elementFromString(final String string) {
		return field.elementFromString(string);
	}
	
	@Override
	public BigInteger getElementIndex(final T element) {
		return field.getElementIndex(element);
	}

}
