ActivatedVectorEventState.java

package net.finmath.finitedifference.assetderivativevaluation.products.internal;

import java.util.Map;

/**
 * Event state containing activated value vectors indexed by event time.
 *
 * <p>
 * This class is used by discretely monitored products whose event condition
 * replaces a pre-event value vector by an activated continuation vector at
 * selected monitoring dates. The vectors are stored in a map keyed by event
 * time. Lookup is performed using a configurable absolute time tolerance, so
 * that event times generated by a time discretization may still match the
 * product's monitoring times despite small floating-point differences.
 * </p>
 *
 * <p>
 * The class does not copy the supplied map or its vector values. Callers should
 * therefore provide already-owned data or treat the supplied map and vectors as
 * immutable after construction.
 * </p>
 *
 * @author Alessandro Gnoatto
 */
public final class ActivatedVectorEventState {

	private final Map<Double, double[]> activatedVectorsAtEventTimes;
	/**
	 * The time tolerance.
	 */
	private final double timeTolerance;

	/**
	 * Creates an event state containing activated vectors keyed by event time.
	 *
	 * @param activatedVectorsAtEventTimes The activated value vectors keyed by
	 *        event time.
	 * @param timeTolerance The non-negative absolute tolerance used when
	 *     matching
	 *        requested event times to stored event times.
	 * @throws IllegalArgumentException Thrown if {@code
	 *     activatedVectorsAtEventTimes}
	 *         is {@code null} or if {@code timeTolerance} is negative.
	 */
	public ActivatedVectorEventState(
			final Map<Double, double[]> activatedVectorsAtEventTimes,
			final double timeTolerance) {

		if (activatedVectorsAtEventTimes == null) {
			throw new IllegalArgumentException("activatedVectorsAtEventTimes must not be null.");
		}
		if (timeTolerance < 0.0) {
			throw new IllegalArgumentException("timeTolerance must be non-negative.");
		}

		this.activatedVectorsAtEventTimes = activatedVectorsAtEventTimes;
		this.timeTolerance = timeTolerance;
	}

	/**
	 * Returns the activated value vector corresponding to the given event time.
	 *
	 * <p>
	 * A stored vector is considered a match if the absolute difference between
	 * the stored event time and the requested event time is less than or equal
	 * to
	 * the configured time tolerance.
	 * </p>
	 *
	 * @param eventTime The requested event time.
	 * @return The activated value vector associated with the matching event
	 *     time.
	 * @throws IllegalArgumentException Thrown if no activated vector is found
	 *         within the configured time tolerance.
	 */
	public double[] getActivatedVector(final double eventTime) {

		for (final Map.Entry<Double, double[]> entry : activatedVectorsAtEventTimes.entrySet()) {
			if (Math.abs(entry.getKey() - eventTime) <= timeTolerance) {
				return entry.getValue();
			}
		}

		throw new IllegalArgumentException(
				"No activated vector found for event time " + eventTime + "."
				);
	}
}