1 /* 2 * Copyright (C) 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 var count = output.length; 27 28 var itemTotals = {}; 29 itemTotals.length = count; 30 31 var total = 0; 32 var categoryTotals = {}; 33 var testTotalsByCategory = {}; 34 35 var mean = 0; 36 var categoryMeans = {}; 37 var testMeansByCategory = {}; 38 39 var stdDev = 0; 40 var categoryStdDevs = {}; 41 var testStdDevsByCategory = {}; 42 43 var stdErr = 0; 44 var categoryStdErrs = {}; 45 var testStdErrsByCategory = {}; 46 47 function initialize() 48 { 49 itemTotals = {total: []}; 50 51 for (var i = 0; i < categories.length; i++) { 52 var category = categories[i]; 53 itemTotals[category] = []; 54 categoryTotals[category] = 0; 55 testTotalsByCategory[category] = {}; 56 categoryMeans[category] = 0; 57 testMeansByCategory[category] = {}; 58 categoryStdDevs[category] = 0; 59 testStdDevsByCategory[category] = {}; 60 categoryStdErrs[category] = 0; 61 testStdErrsByCategory[category] = {}; 62 } 63 64 for (var i = 0; i < tests.length; i++) { 65 var test = tests[i]; 66 itemTotals[test] = []; 67 var category = test.replace(/-.*/, ""); 68 testTotalsByCategory[category][test] = 0; 69 testMeansByCategory[category][test] = 0; 70 testStdDevsByCategory[category][test] = 0; 71 testStdErrsByCategory[category][test] = 0; 72 } 73 74 for (var i = 0; i < count; i++) { 75 itemTotals["total"][i] = 0; 76 for (var category in categoryTotals) { 77 itemTotals[category][i] = 0; 78 for (var test in testTotalsByCategory[category]) { 79 itemTotals[test][i] = 0; 80 } 81 } 82 } 83 } 84 85 function computeItemTotals() 86 { 87 for (var i = 0; i < output.length; i++) { 88 var result = output[i]; 89 for (var test in result) { 90 var time = result[test]; 91 var category = test.replace(/-.*/, ""); 92 itemTotals["total"][i] += time; 93 itemTotals[category][i] += time; 94 itemTotals[test][i] += time; 95 } 96 } 97 } 98 99 function computeTotals() 100 { 101 for (var i = 0; i < output.length; i++) { 102 var result = output[i]; 103 for (var test in result) { 104 var time = result[test]; 105 var category = test.replace(/-.*/, ""); 106 total += time; 107 categoryTotals[category] += time; 108 testTotalsByCategory[category][test] += time; 109 } 110 } 111 } 112 113 function computeMeans() 114 { 115 mean = total / count; 116 for (var category in categoryTotals) { 117 categoryMeans[category] = categoryTotals[category] / count; 118 for (var test in testTotalsByCategory[category]) { 119 testMeansByCategory[category][test] = testTotalsByCategory[category][test] / count; 120 } 121 } 122 } 123 124 function standardDeviation(mean, items) 125 { 126 var deltaSquaredSum = 0; 127 for (var i = 0; i < items.length; i++) { 128 var delta = items[i] - mean; 129 deltaSquaredSum += delta * delta; 130 } 131 variance = deltaSquaredSum / (items.length - 1); 132 return Math.sqrt(variance); 133 } 134 135 function computeStdDevs() 136 { 137 stdDev = standardDeviation(mean, itemTotals["total"]); 138 for (var category in categoryStdDevs) { 139 categoryStdDevs[category] = standardDeviation(categoryMeans[category], itemTotals[category]); 140 } 141 for (var category in categoryStdDevs) { 142 for (var test in testStdDevsByCategory[category]) { 143 testStdDevsByCategory[category][test] = standardDeviation(testMeansByCategory[category][test], itemTotals[test]); 144 } 145 } 146 } 147 148 function computeStdErrors() 149 { 150 var sqrtCount = Math.sqrt(count); 151 152 stdErr = stdDev / sqrtCount; 153 for (var category in categoryStdErrs) { 154 categoryStdErrs[category] = categoryStdDevs[category] / sqrtCount; 155 } 156 for (var category in categoryStdDevs) { 157 for (var test in testStdErrsByCategory[category]) { 158 testStdErrsByCategory[category][test] = testStdDevsByCategory[category][test] / sqrtCount; 159 } 160 } 161 162 } 163 164 var tDistribution = [NaN, NaN, 12.71, 4.30, 3.18, 2.78, 2.57, 2.45, 2.36, 2.31, 2.26, 2.23, 2.20, 2.18, 2.16, 2.14, 2.13, 2.12, 2.11, 2.10, 2.09, 2.09, 2.08, 2.07, 2.07, 2.06, 2.06, 2.06, 2.05, 2.05, 2.05, 2.04, 2.04, 2.04, 2.03, 2.03, 2.03, 2.03, 2.03, 2.02, 2.02, 2.02, 2.02, 2.02, 2.02, 2.02, 2.01, 2.01, 2.01, 2.01, 2.01, 2.01, 2.01, 2.01, 2.01, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 2.00, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.99, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.98, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.97, 1.96]; 165 var tMax = tDistribution.length; 166 var tLimit = 1.96; 167 168 function tDist(n) 169 { 170 if (n > tMax) 171 return tLimit; 172 return tDistribution[n]; 173 } 174 175 176 function formatResult(meanWidth, mean, stdErr, n) 177 { 178 var meanString = mean.toFixed(1).toString(); 179 while (meanString.length < meanWidth) { 180 meanString = " " + meanString; 181 } 182 183 if (n == 1) 184 return meanString + "ms"; 185 186 return meanString + "ms +/- " + ((tDist(n) * stdErr / mean) * 100).toFixed(1) + "%"; 187 } 188 189 function computeLabelWidth() 190 { 191 var width = "Total".length; 192 for (var category in categoryMeans) { 193 if (category.length + 2 > width) 194 width = category.length + 2; 195 } 196 for (var i = 0; i < tests.length; i++) { 197 var shortName = tests[i].replace(/^[^-]*-/, ""); 198 if (shortName.length + 4 > width) 199 width = shortName.length + 4; 200 } 201 202 return width; 203 } 204 205 function computeMeanWidth() 206 { 207 var width = mean.toFixed(1).toString().length; 208 for (var category in categoryMeans) { 209 var candidate = categoryMeans[category].toFixed(2).toString().length; 210 if (candidate > width) 211 width = candidate; 212 for (var test in testMeansByCategory[category]) { 213 var candidate = testMeansByCategory[category][test].toFixed(2).toString().length; 214 if (candidate > width) 215 width = candidate; 216 } 217 } 218 219 return width; 220 } 221 222 function resultLine(labelWidth, indent, label, meanWidth, mean, stdErr) 223 { 224 var result = ""; 225 for (i = 0; i < indent; i++) { 226 result += " "; 227 } 228 229 result += label + ": "; 230 231 for (i = 0; i < (labelWidth - (label.length + indent)); i++) { 232 result += " "; 233 } 234 235 return result + formatResult(meanWidth, mean, stdErr, count); 236 } 237 238 function printOutput() 239 { 240 var labelWidth = computeLabelWidth(); 241 var meanWidth = computeMeanWidth(); 242 243 print("\n"); 244 print("============================================"); 245 if (count == 1) 246 print("RESULTS"); 247 else 248 print("RESULTS (means and 95% confidence intervals)"); 249 print("--------------------------------------------"); 250 print(resultLine(labelWidth, 0, "Total", meanWidth, mean, stdErr)); 251 print("--------------------------------------------"); 252 for (var category in categoryMeans) { 253 print(""); 254 print(resultLine(labelWidth, 2, category, meanWidth, categoryMeans[category], categoryStdErrs[category])); 255 for (var test in testMeansByCategory[category]) { 256 var shortName = test.replace(/^[^-]*-/, ""); 257 print(resultLine(labelWidth, 4, shortName, meanWidth, testMeansByCategory[category][test], testStdErrsByCategory[category][test])); 258 } 259 } 260 } 261 262 initialize(); 263 computeItemTotals(); 264 computeTotals(); 265 computeMeans(); 266 computeStdDevs(); 267 computeStdErrors(); 268 printOutput(); 269