Median.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.  *      https://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.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.stat.descriptive.rank;

  22. import java.io.Serializable;

  23. import org.hipparchus.exception.MathIllegalArgumentException;
  24. import org.hipparchus.exception.NullArgumentException;
  25. import org.hipparchus.stat.descriptive.AbstractUnivariateStatistic;
  26. import org.hipparchus.stat.descriptive.rank.Percentile.EstimationType;
  27. import org.hipparchus.stat.ranking.NaNStrategy;
  28. import org.hipparchus.util.KthSelector;


  29. /**
  30.  * Returns the median of the available values.  This is the same as the 50th percentile.
  31.  * See {@link Percentile} for a description of the algorithm used.
  32.  * <p>
  33.  * <strong>Note that this implementation is not synchronized.</strong> If
  34.  * multiple threads access an instance of this class concurrently, and at least
  35.  * one of the threads invokes the <code>increment()</code> or
  36.  * <code>clear()</code> method, it must be synchronized externally.
  37.  */
  38. public class Median extends AbstractUnivariateStatistic implements Serializable {

  39.     /** Serializable version identifier */
  40.     private static final long serialVersionUID = 20150412L;

  41.     /** Fixed quantile. */
  42.     private static final double FIXED_QUANTILE_50 = 50.0;

  43.     /** The percentile impl to calculate the median. */
  44.     private final Percentile percentile;

  45.     /**
  46.      * Default constructor.
  47.      */
  48.     public Median() {
  49.         percentile = new Percentile(FIXED_QUANTILE_50);
  50.     }

  51.     /**
  52.      * Constructs a Median with the specific {@link EstimationType},
  53.      * {@link NaNStrategy} and {@link KthSelector}.
  54.      *
  55.      * @param estimationType one of the percentile {@link EstimationType estimation types}
  56.      * @param nanStrategy one of {@link NaNStrategy} to handle with NaNs
  57.      * @param kthSelector {@link KthSelector} to use for pivoting during search
  58.      * @throws MathIllegalArgumentException if p is not within (0,100]
  59.      * @throws NullArgumentException if type or NaNStrategy passed is null
  60.      */
  61.     private Median(final EstimationType estimationType, final NaNStrategy nanStrategy,
  62.                    final KthSelector kthSelector)
  63.         throws MathIllegalArgumentException {

  64.         percentile = new Percentile(FIXED_QUANTILE_50, estimationType,
  65.                                     nanStrategy, kthSelector);
  66.     }

  67.     /**
  68.      * Copy constructor, creates a new {@code Median} identical
  69.      * to the {@code original}
  70.      *
  71.      * @param original the {@code Median} instance to copy
  72.      * @throws NullArgumentException if original is null
  73.      */
  74.     Median(Median original) throws NullArgumentException {
  75.         super(original);
  76.         this.percentile = original.percentile.copy();
  77.     }

  78.     /** {@inheritDoc} */
  79.     @Override
  80.     public double evaluate(double[] values, int begin, int length)
  81.         throws MathIllegalArgumentException {
  82.         return percentile.evaluate(values, begin, length);
  83.     }

  84.     /** {@inheritDoc} */
  85.     @Override
  86.     public Median copy() {
  87.         return new Median(this);
  88.     }

  89.     /**
  90.      * Get the estimation {@link EstimationType type} used for computation.
  91.      *
  92.      * @return the {@code estimationType} set
  93.      */
  94.     public EstimationType getEstimationType() {
  95.         return percentile.getEstimationType();
  96.     }

  97.     /**
  98.      * Build a new instance similar to the current one except for the
  99.      * {@link EstimationType estimation type}.
  100.      *
  101.      * @param newEstimationType estimation type for the new instance
  102.      * @return a new instance, with changed estimation type
  103.      * @throws NullArgumentException when newEstimationType is null
  104.      */
  105.     public Median withEstimationType(final EstimationType newEstimationType) {
  106.         return new Median(newEstimationType,
  107.                           percentile.getNaNStrategy(),
  108.                           percentile.getKthSelector());
  109.     }

  110.     /**
  111.      * Get the {@link NaNStrategy NaN Handling} strategy used for computation.
  112.      * @return {@code NaN Handling} strategy set during construction
  113.      */
  114.     public NaNStrategy getNaNStrategy() {
  115.         return percentile.getNaNStrategy();
  116.     }

  117.     /**
  118.      * Build a new instance similar to the current one except for the
  119.      * {@link NaNStrategy NaN handling} strategy.
  120.      *
  121.      * @param newNaNStrategy NaN strategy for the new instance
  122.      * @return a new instance, with changed NaN handling strategy
  123.      * @throws NullArgumentException when newNaNStrategy is null
  124.      */
  125.     public Median withNaNStrategy(final NaNStrategy newNaNStrategy) {
  126.         return new Median(percentile.getEstimationType(),
  127.                           newNaNStrategy,
  128.                           percentile.getKthSelector());
  129.     }

  130.     /**
  131.      * Get the {@link KthSelector kthSelector} used for computation.
  132.      * @return the {@code kthSelector} set
  133.      */
  134.     public KthSelector getKthSelector() {
  135.         return percentile.getKthSelector();
  136.     }

  137.     /**
  138.      * Build a new instance similar to the current one except for the
  139.      * {@link KthSelector kthSelector} instance specifically set.
  140.      *
  141.      * @param newKthSelector KthSelector for the new instance
  142.      * @return a new instance, with changed KthSelector
  143.      * @throws NullArgumentException when newKthSelector is null
  144.      */
  145.     public Median withKthSelector(final KthSelector newKthSelector) {
  146.         return new Median(percentile.getEstimationType(),
  147.                           percentile.getNaNStrategy(),
  148.                           newKthSelector);
  149.     }

  150. }