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 018 package org.apache.commons.math3.analysis.function; 019 020 import java.util.Arrays; 021 import org.apache.commons.math3.analysis.UnivariateFunction; 022 import org.apache.commons.math3.exception.DimensionMismatchException; 023 import org.apache.commons.math3.exception.NullArgumentException; 024 import org.apache.commons.math3.exception.NoDataException; 025 import org.apache.commons.math3.util.MathArrays; 026 027 /** 028 * <a href="http://en.wikipedia.org/wiki/Step_function"> 029 * Step function</a>. 030 * 031 * @since 3.0 032 * @version $Id: StepFunction.java 1379218 2012-08-30 23:18:57Z erans $ 033 */ 034 public class StepFunction implements UnivariateFunction { 035 /** Abscissae. */ 036 private final double[] abscissa; 037 /** Ordinates. */ 038 private final double[] ordinate; 039 040 /** 041 * Builds a step function from a list of arguments and the corresponding 042 * values. Specifically, returns the function h(x) defined by <pre><code> 043 * h(x) = y[0] for all x < x[1] 044 * y[1] for x[1] <= x < x[2] 045 * ... 046 * y[y.length - 1] for x >= x[x.length - 1] 047 * </code></pre> 048 * The value of {@code x[0]} is ignored, but it must be strictly less than 049 * {@code x[1]}. 050 * 051 * @param x Domain values where the function changes value. 052 * @param y Values of the function. 053 * @throws org.apache.commons.math3.exception.NonMonotonicSequenceException 054 * if the {@code x} array is not sorted in strictly increasing order. 055 * @throws NullArgumentException if {@code x} or {@code y} are {@code null}. 056 * @throws NoDataException if {@code x} or {@code y} are zero-length. 057 * @throws DimensionMismatchException if {@code x} and {@code y} do not 058 * have the same length. 059 */ 060 public StepFunction(double[] x, 061 double[] y) 062 throws NullArgumentException, 063 NoDataException, 064 DimensionMismatchException { 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 = MathArrays.copyOf(x); 079 ordinate = MathArrays.copyOf(y); 080 } 081 082 /** {@inheritDoc} */ 083 public double value(double x) { 084 int index = Arrays.binarySearch(abscissa, x); 085 double fx = 0; 086 087 if (index < -1) { 088 // "x" is between "abscissa[-index-2]" and "abscissa[-index-1]". 089 fx = ordinate[-index-2]; 090 } else if (index >= 0) { 091 // "x" is exactly "abscissa[index]". 092 fx = ordinate[index]; 093 } else { 094 // Otherwise, "x" is smaller than the first value in "abscissa" 095 // (hence the returned value should be "ordinate[0]"). 096 fx = ordinate[0]; 097 } 098 099 return fx; 100 } 101 }