package com.srbenoit.math.optimizers;

/**
 * A range of data values over which to search for minima. This represents an open box in R^n.
 */
public class SearchRange {

    /** the ranges */
    private final transient double[][] ranges;

    /**
     * Constructs a new <code>SearchRange</code>.
     *
     * @param  dimension  the dimension of the data
     */
    public SearchRange(final int dimension) {

        this.ranges = new double[dimension][2];
    }

    /**
     * Gets the dimension of the search range.
     *
     * @return  the dimension
     */
    public int getDimension() {

        return this.ranges.length;
    }

    /**
     * Sets a range along a particular variable.
     *
     * @param  index  the variable index
     * @param  min    the minimum value
     * @param  max    the maximum value
     */
    public void setRange(final int index, final double min, final double max) {

        if (max >= min) {
            this.ranges[index][0] = min;
            this.ranges[index][1] = max;
        } else {
            this.ranges[index][0] = max;
            this.ranges[index][1] = min;
        }
    }

    /**
     * Gets the minimum value for a particular variable.
     *
     * @param   index  the variable index
     * @return  the minimum value
     */
    public double getMin(final int index) {

        return this.ranges[index][0];
    }

    /**
     * Gets the maximum value for a particular variable.
     *
     * @param   index  the variable index
     * @return  the maxSimum value
     */
    public double getMax(final int index) {

        return this.ranges[index][1];
    }

    /**
     * Tests whether a point is in the range.
     *
     * @param   point  the point to test
     * @return  <code>true</code> if the point is within the box in every dimension; <code>
     *          false</code> otherwise
     */
    public boolean containsPoint(final double[] point) {

        boolean inRange = true;

        for (int i = 0; i < this.ranges.length; i++) {

            if (point[i] < this.ranges[i][0]) {
                inRange = false;

                break;
            }

            if (point[i] > this.ranges[i][1]) {
                inRange = false;

                break;
            }
        }

        return inRange;
    }
}
