001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.math4.legacy.analysis.function; 019 020import java.util.Arrays; 021 022import org.apache.commons.math4.legacy.analysis.UnivariateFunction; 023import org.apache.commons.math4.legacy.exception.DimensionMismatchException; 024import org.apache.commons.math4.legacy.exception.NoDataException; 025import org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException; 026import org.apache.commons.math4.legacy.exception.NullArgumentException; 027import org.apache.commons.math4.legacy.core.MathArrays; 028 029/** 030 * <a href="http://en.wikipedia.org/wiki/Step_function"> 031 * Step function</a>. 032 * 033 * @since 3.0 034 */ 035public class StepFunction implements UnivariateFunction { 036 /** Abscissae. */ 037 private final double[] abscissa; 038 /** Ordinates. */ 039 private final double[] ordinate; 040 041 /** 042 * Builds a step function from a list of arguments and the corresponding 043 * values. Specifically, returns the function h(x) defined by <pre><code> 044 * h(x) = y[0] for all x < x[1] 045 * y[1] for x[1] ≤ x < x[2] 046 * ... 047 * y[y.length - 1] for x ≥ x[x.length - 1] 048 * </code></pre> 049 * The value of {@code x[0]} is ignored, but it must be strictly less than 050 * {@code x[1]}. 051 * 052 * @param x Domain values where the function changes value. 053 * @param y Values of the function. 054 * @throws NonMonotonicSequenceException 055 * if the {@code x} array is not sorted in strictly increasing order. 056 * @throws NullArgumentException if {@code x} or {@code y} are {@code null}. 057 * @throws NoDataException if {@code x} or {@code y} are zero-length. 058 * @throws DimensionMismatchException if {@code x} and {@code y} do not 059 * have the same length. 060 */ 061 public StepFunction(double[] x, 062 double[] y) 063 throws NullArgumentException, NoDataException, 064 DimensionMismatchException, NonMonotonicSequenceException { 065 if (x == null || 066 y == null) { 067 throw new NullArgumentException(); 068 } 069 if (x.length == 0 || 070 y.length == 0) { 071 throw new NoDataException(); 072 } 073 if (y.length != x.length) { 074 throw new DimensionMismatchException(y.length, x.length); 075 } 076 MathArrays.checkOrder(x); 077 078 abscissa = Arrays.copyOf(x, x.length); 079 ordinate = Arrays.copyOf(y, y.length); 080 } 081 082 /** {@inheritDoc} */ 083 @Override 084 public double value(double x) { 085 int index = Arrays.binarySearch(abscissa, x); 086 double fx = 0; 087 088 if (index < -1) { 089 // "x" is between "abscissa[-index-2]" and "abscissa[-index-1]". 090 fx = ordinate[-index-2]; 091 } else if (index >= 0) { 092 // "x" is exactly "abscissa[index]". 093 fx = ordinate[index]; 094 } else { 095 // Otherwise, "x" is smaller than the first value in "abscissa" 096 // (hence the returned value should be "ordinate[0]"). 097 fx = ordinate[0]; 098 } 099 100 return fx; 101 } 102}