/**
* Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.data.scenario;
import java.util.List;
import java.util.function.IntFunction;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
* An array of values, one for each scenario.
* <p>
* Implementations of this interface provide scenario-specific values.
* <p>
* In the simplest case, this might be a list of values, one for each scenario.
* This is handled by this factory methods on this interface.
* <p>
* There are two obvious reasons for creating implementations of this interface with
* special handling for certain types of value:
* <ul>
* <li>Reducing memory usage</li>
* <li>Improving performance</li>
* </ul>
* For example, if the system stores multiple copies of a curve as a list it must store the x-values with
* each copy of the curve. This data is mostly redundant as the x-values are the same in every scenario.
* A custom data type for storing scenario data for a curve can store one set of x-values shared between
* all scenarios, reducing memory footprint.
* <p>
* When dealing with primitive data it is likely be more efficient to store the scenario values in a primitive
* array instead of using a list. This removes the need for boxing and reduces memory footprint.
* Also, if a function calculates values for all scenarios at the same time, it is likely to be more efficient
* if the data is stored in arrays as the values will be stored in a contiguous block of memory.
* <p>
* The generic type parameter is the type of the single value associated with each scenario.
* For example, in the case of optimized curve storage, the single value is a curve.
*
* @param <T> the type of each individual value
*/
public interface ScenarioArray<T> {
/**
* Obtains an instance from the specified array of values.
*
* @param <T> the type of the value
* @param values the values, one value for each scenario
* @return an instance with the specified values
*/
@SafeVarargs
public static <T> ScenarioArray<T> of(T... values) {
return DefaultScenarioArray.of(values);
}
/**
* Obtains an instance from the specified list of values.
*
* @param <T> the type of the value
* @param values the values, one value for each scenario
* @return an instance with the specified values
*/
public static <T> ScenarioArray<T> of(List<T> values) {
return DefaultScenarioArray.of(values);
}
/**
* Obtains an instance using a function to create the entries.
* <p>
* The function is passed the scenario index and returns the value for that index.
*
* @param <T> the type of the value
* @param scenarioCount the number of scenarios
* @param valueFunction the function used to obtain each value
* @return an instance initialized using the function
* @throws IllegalArgumentException is size is zero or less
*/
public static <T> ScenarioArray<T> of(int scenarioCount, IntFunction<T> valueFunction) {
return DefaultScenarioArray.of(scenarioCount, valueFunction);
}
//-------------------------------------------------------------------------
/**
* Obtains an instance from a single value where the value applies to all scenarios.
*
* @param <T> the type of the value
* @param scenarioCount the nnumber of scenarios
* @param value the single value, used for all scenarios
* @return an instance with the specified values
*/
public static <T> ScenarioArray<T> ofSingleValue(int scenarioCount, T value) {
return SingleScenarioArray.of(scenarioCount, value);
}
//-------------------------------------------------------------------------
/**
* Gets the number of scenarios.
*
* @return the number of scenarios
*/
public abstract int getScenarioCount();
/**
* Gets the value at the specified scenario index.
*
* @param scenarioIndex the zero-based index of the scenario
* @return the value at the specified index
* @throws IndexOutOfBoundsException if the index is invalid
*/
public abstract T get(int scenarioIndex);
/**
* Returns a stream of the values.
* <p>
* The stream will return the value for each scenario.
*
* @return a stream of the values
*/
public default Stream<T> stream() {
return IntStream.range(0, getScenarioCount()).mapToObj(i -> get(i));
}
}