@@ -34,6 +34,7 @@ class `ReportFormatter` creates the test comparison report in specified format.
3434import sys
3535from bisect import bisect , bisect_left , bisect_right
3636from collections import namedtuple
37+ from decimal import Decimal , ROUND_HALF_EVEN
3738from math import sqrt
3839
3940
@@ -141,24 +142,32 @@ def max(self):
141142 """Maximum sampled value."""
142143 return self .samples [- 1 ].runtime
143144
144- def _quantile_index (self , q , i ):
145- """Return index of the element nearest to the i-th q-quantile."""
146- return int (round ((self .count - 1 ) / float (q ) * float (i )))
145+ def quantile (self , q ):
146+ """Return runtime of a sample nearest to the quantile.
147+
148+ Explicitly uses round-half-to-even rounding algorithm to match the
149+ behavior of numpy's quantile(interpolation='nearest') and quantile
150+ estimate type R-3, SAS-2. See:
151+ https://en.wikipedia.org/wiki/Quantile#Estimating_quantiles_from_a_sample
152+ """
153+ index = int (Decimal ((self .count - 1 ) * Decimal (q ))
154+ .quantize (0 , ROUND_HALF_EVEN ))
155+ return self .samples [index ].runtime
147156
148157 @property
149158 def median (self ):
150159 """Median sampled value."""
151- return self .samples [ self . _quantile_index ( 2 , 1 )]. runtime
160+ return self .quantile ( 0.5 )
152161
153162 @property
154163 def q1 (self ):
155164 """First Quartile (25th Percentile)."""
156- return self .samples [ self . _quantile_index ( 4 , 1 )]. runtime
165+ return self .quantile ( 0.25 )
157166
158167 @property
159168 def q3 (self ):
160169 """Third Quartile (75th Percentile)."""
161- return self .samples [ self . _quantile_index ( 4 , 3 )]. runtime
170+ return self .quantile ( 0.75 )
162171
163172 @property
164173 def iqr (self ):
0 commit comments