1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.math4.legacy.analysis.function; 19 20 import java.util.Arrays; 21 22 import org.apache.commons.math4.legacy.analysis.UnivariateFunction; 23 import org.apache.commons.math4.legacy.exception.DimensionMismatchException; 24 import org.apache.commons.math4.legacy.exception.NoDataException; 25 import org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException; 26 import org.apache.commons.math4.legacy.exception.NullArgumentException; 27 import org.apache.commons.math4.legacy.core.MathArrays; 28 29 /** 30 * <a href="http://en.wikipedia.org/wiki/Step_function"> 31 * Step function</a>. 32 * 33 * @since 3.0 34 */ 35 public class StepFunction implements UnivariateFunction { 36 /** Abscissae. */ 37 private final double[] abscissa; 38 /** Ordinates. */ 39 private final double[] ordinate; 40 41 /** 42 * Builds a step function from a list of arguments and the corresponding 43 * values. Specifically, returns the function h(x) defined by <pre><code> 44 * h(x) = y[0] for all x < x[1] 45 * y[1] for x[1] ≤ x < x[2] 46 * ... 47 * y[y.length - 1] for x ≥ x[x.length - 1] 48 * </code></pre> 49 * The value of {@code x[0]} is ignored, but it must be strictly less than 50 * {@code x[1]}. 51 * 52 * @param x Domain values where the function changes value. 53 * @param y Values of the function. 54 * @throws NonMonotonicSequenceException 55 * if the {@code x} array is not sorted in strictly increasing order. 56 * @throws NullArgumentException if {@code x} or {@code y} are {@code null}. 57 * @throws NoDataException if {@code x} or {@code y} are zero-length. 58 * @throws DimensionMismatchException if {@code x} and {@code y} do not 59 * have the same length. 60 */ 61 public StepFunction(double[] x, 62 double[] y) 63 throws NullArgumentException, NoDataException, 64 DimensionMismatchException, NonMonotonicSequenceException { 65 if (x == null || 66 y == null) { 67 throw new NullArgumentException(); 68 } 69 if (x.length == 0 || 70 y.length == 0) { 71 throw new NoDataException(); 72 } 73 if (y.length != x.length) { 74 throw new DimensionMismatchException(y.length, x.length); 75 } 76 MathArrays.checkOrder(x); 77 78 abscissa = Arrays.copyOf(x, x.length); 79 ordinate = Arrays.copyOf(y, y.length); 80 } 81 82 /** {@inheritDoc} */ 83 @Override 84 public double value(double x) { 85 int index = Arrays.binarySearch(abscissa, x); 86 double fx = 0; 87 88 if (index < -1) { 89 // "x" is between "abscissa[-index-2]" and "abscissa[-index-1]". 90 fx = ordinate[-index-2]; 91 } else if (index >= 0) { 92 // "x" is exactly "abscissa[index]". 93 fx = ordinate[index]; 94 } else { 95 // Otherwise, "x" is smaller than the first value in "abscissa" 96 // (hence the returned value should be "ordinate[0]"). 97 fx = ordinate[0]; 98 } 99 100 return fx; 101 } 102 }