package ec.gp.semantic;


/**
 * Base class for semantics. The values of semantics are immutable!
 *
 * @param <TSemStore>
 * @author Tomasz Pawlak
 */
public abstract class SemanticsBase<TSemStore> implements ISemantics {

	// 2^-52 = 0x3FF0000000000000L - 0x0340000000000000L
	private static final double SENSITIVITY = Double.longBitsToDouble(0x3CB0000000000000L);

	protected TSemStore value;

	public SemanticsBase(TSemStore values) {
		this.value = values;
	}

	@Override
	public SemanticsBase<TSemStore> clone() {
		try {
			return (SemanticsBase<TSemStore>) super.clone();
		} catch (CloneNotSupportedException e) {
			assert false : "this should never happen";
			return null;
		}
	}

	@Override
	public double distanceTo(ISemantics other, double p) {
		return Math.pow(this.fastDistanceTo(other, p), 1.0 / p);
	}

	@Override
	public boolean isBetween(ISemantics semantics1, ISemantics semantics2, double p) {
		final double distanceBetweenTwoOther = semantics1.distanceTo(semantics2, p);
		final double distanceBetweenMeAndSem1 = this.distanceTo(semantics1, p);
		final double distanceBetweenMeAndSem2 = this.distanceTo(semantics2, p);

		return Math.abs(distanceBetweenTwoOther - distanceBetweenMeAndSem1 - distanceBetweenMeAndSem2) < SENSITIVITY // geometry
				&& !this.equals(semantics1) && !this.equals(semantics2); // effectiveness
	}

	public Object getValue() {
		return this.value;
	}
}
