ErfDifference.java

  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. package org.apache.commons.numbers.gamma;

  18. /**
  19.  * Computes the difference between {@link Erf error function values}.
  20.  */
  21. public final class ErfDifference {
  22.     /**
  23.      * This number solves {@code erf(x) = 0.5} within 1 ulp.
  24.      * More precisely, the current implementations of
  25.      * {@link Erf#value(double)} and {@link Erfc#value(double)} satisfy:
  26.      * <ul>
  27.      *  <li>{@code Erf.value(X_CRIT) == 0.5},</li>
  28.      *  <li>{@code Erf.value(Math.nextUp(X_CRIT)) > 0.5},</li>
  29.      *  <li>{@code Erfc.value(X_CRIT) == 0.5}, and</li>
  30.      *  <li>{@code Erfc.value(Math.nextUp(X_CRIT)) < 0.5}</li>
  31.      * </ul>
  32.      */
  33.     private static final double X_CRIT = 0.47693627620446993;

  34.     /** Private constructor. */
  35.     private ErfDifference() {
  36.         // intentionally empty.
  37.     }

  38.     /**
  39.      * The implementation uses either {@link Erf} or {@link Erfc},
  40.      * depending on which provides the most precise result.
  41.      *
  42.      * @param x1 First value.
  43.      * @param x2 Second value.
  44.      * @return {@link Erf#value(double) Erf.value(x2) - Erf.value(x1)}.
  45.      * @throws ArithmeticException if the algorithm fails to converge.
  46.      */
  47.     public static double value(double x1,
  48.                                double x2) {
  49.         if (x1 > x2) {
  50.             return -value(x2, x1);
  51.         }
  52.         if (x1 < -X_CRIT) {
  53.             if (x2 < 0) {
  54.                 return Erfc.value(-x2) - Erfc.value(-x1);
  55.             }
  56.             return Erf.value(x2) - Erf.value(x1);
  57.         }
  58.         if (x2 > X_CRIT &&
  59.             x1 > 0) {
  60.             return Erfc.value(x1) - Erfc.value(x2);
  61.         }
  62.         return Erf.value(x2) - Erf.value(x1);
  63.     }
  64. }