Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.compatibility.common.util;
     18 
     19 import java.util.Arrays;
     20 
     21 /**
     22  * Utilities for doing statistics
     23  */
     24 public class Stat {
     25     /**
     26      * Private constructor for static class.
     27      */
     28     private Stat() {}
     29 
     30     /**
     31      * Collection of statistical propertirs like average, max, min, and stddev
     32      */
     33     public static class StatResult {
     34         public double mAverage;
     35         public double mMin;
     36         public double mMax;
     37         public double mStddev;
     38         public int mDataCount;
     39         public StatResult(double average, double min, double max, double stddev, int dataCount) {
     40             mAverage = average;
     41             mMin = min;
     42             mMax = max;
     43             mStddev = stddev;
     44             mDataCount = dataCount;
     45         }
     46     }
     47 
     48     /**
     49      * Calculate statistics properties likes average, min, max, and stddev for the given array
     50      */
     51     public static StatResult getStat(double[] data) {
     52         double average = data[0];
     53         double min = data[0];
     54         double max = data[0];
     55         for (int i = 1; i < data.length; i++) {
     56             average += data[i];
     57             if (data[i] > max) {
     58                 max = data[i];
     59             }
     60             if (data[i] < min) {
     61                 min = data[i];
     62             }
     63         }
     64         average /= data.length;
     65         double sumOfSquares = 0.0;
     66         for (int i = 0; i < data.length; i++) {
     67             double diff = average - data[i];
     68             sumOfSquares += diff * diff;
     69         }
     70         double variance = sumOfSquares / (data.length - 1);
     71         double stddev = Math.sqrt(variance);
     72         return new StatResult(average, min, max, stddev, data.length);
     73     }
     74 
     75     /**
     76      * Calculate statistics properties likes average, min, max, and stddev for the given array
     77      * while rejecting outlier +/- median * rejectionThreshold.
     78      * rejectionThreshold should be bigger than 0.0 and be lowerthan 1.0
     79      */
     80     public static StatResult getStatWithOutlierRejection(double[] data, double rejectionThreshold) {
     81         double[] dataCopied = Arrays.copyOf(data, data.length);
     82         Arrays.sort(dataCopied);
     83         int medianIndex = dataCopied.length / 2;
     84         double median;
     85         if (dataCopied.length % 2 == 1) {
     86             median = dataCopied[medianIndex];
     87         } else {
     88             median = (dataCopied[medianIndex - 1] + dataCopied[medianIndex]) / 2.0;
     89         }
     90         double thresholdMin = median * (1.0 - rejectionThreshold);
     91         double thresholdMax = median * (1.0 + rejectionThreshold);
     92 
     93         double[] validData = new double[data.length];
     94         int index = 0;
     95         for (int i = 0; i < data.length; i++) {
     96             if ((data[i] > thresholdMin) && (data[i] < thresholdMax)) {
     97                 validData[index] = data[i];
     98                 index++;
     99             }
    100             // TODO report rejected data
    101         }
    102         return getStat(Arrays.copyOf(validData, index));
    103     }
    104 
    105     /**
    106      * return the average value of the passed array
    107      */
    108     public static double getAverage(double[] data) {
    109         double sum = data[0];
    110         for (int i = 1; i < data.length; i++) {
    111             sum += data[i];
    112         }
    113         return sum / data.length;
    114     }
    115 
    116     /**
    117      * return the minimum value of the passed array
    118      */
    119     public static double getMin(double[] data) {
    120         double min = data[0];
    121         for (int i = 1; i < data.length; i++) {
    122             if (data[i] < min) {
    123                 min = data[i];
    124             }
    125         }
    126         return min;
    127     }
    128 
    129     /**
    130      * return the maximum value of the passed array
    131      */
    132     public static double getMax(double[] data) {
    133         double max = data[0];
    134         for (int i = 1; i < data.length; i++) {
    135             if (data[i] > max) {
    136                 max = data[i];
    137             }
    138         }
    139         return max;
    140     }
    141 
    142     /**
    143      * Calculate rate per sec for given change happened during given timeInMSec.
    144      * timeInSec with 0 value will be changed to small value to prevent divide by zero.
    145      * @param change total change of quality for the given duration timeInMSec.
    146      * @param timeInMSec
    147      */
    148     public static double calcRatePerSec(double change, double timeInMSec) {
    149         if (timeInMSec == 0) {
    150             return change * 1000.0 / 0.001; // do not allow zero
    151         } else {
    152             return change * 1000.0 / timeInMSec;
    153         }
    154     }
    155 
    156     /**
    157      * array version of calcRatePerSecArray
    158      */
    159     public static double[] calcRatePerSecArray(double change, double[] timeInMSec) {
    160         double[] result = new double[timeInMSec.length];
    161         change *= 1000.0;
    162         for (int i = 0; i < timeInMSec.length; i++) {
    163             if (timeInMSec[i] == 0) {
    164                 result[i] = change / 0.001;
    165             } else {
    166                 result[i] = change / timeInMSec[i];
    167             }
    168         }
    169         return result;
    170     }
    171 
    172     /**
    173      * Get the value of the 95th percentile using nearest rank algorithm.
    174      */
    175     public static double get95PercentileValue(double[] values) {
    176         Arrays.sort(values);
    177         // zero-based array index
    178         int index = (int) Math.round(values.length * 0.95 + .5) - 1;
    179         return values[index];
    180     }
    181 
    182 }
    183