180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru''' 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruCreated on May 19, 2011 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru@author: bungeman 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru''' 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport re 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruimport math 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger# bench representation algorithm constant names 11363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerALGORITHM_AVERAGE = 'avg' 12363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerALGORITHM_MEDIAN = 'med' 13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerALGORITHM_MINIMUM = 'min' 14363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerALGORITHM_25TH_PERCENTILE = '25th' 15363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass BenchDataPoint: 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru """A single data point produced by bench. 18363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (str, str, str, float, {str:str})""" 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru def __init__(self, bench, config, time_type, time, settings): 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.bench = bench 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.config = config 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.time_type = time_type 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.time = time 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.settings = settings 26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru def __repr__(self): 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return "BenchDataPoint(%s, %s, %s, %s, %s)" % ( 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str(self.bench), 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str(self.config), 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str(self.time_type), 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str(self.time), 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str(self.settings), 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ) 35363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass _ExtremeType(object): 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru """Instances of this class compare greater or less than other objects.""" 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru def __init__(self, cmpr, rep): 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru object.__init__(self) 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self._cmpr = cmpr 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self._rep = rep 42363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru def __cmp__(self, other): 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if isinstance(other, self.__class__) and other._cmpr == self._cmpr: 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 0 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return self._cmpr 47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru def __repr__(self): 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return self._rep 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruMax = _ExtremeType(1, "Max") 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruMin = _ExtremeType(-1, "Min") 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass _ListAlgorithm(object): 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru """Algorithm for selecting the representation value from a given list. 56363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger representation is one of the ALGORITHM_XXX representation types.""" 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru def __init__(self, data, representation=None): 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if not representation: 59363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger representation = ALGORITHM_AVERAGE # default algorithm 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self._data = data 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self._len = len(data) 62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger if representation == ALGORITHM_AVERAGE: 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self._rep = sum(self._data) / self._len 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru else: 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self._data.sort() 66363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger if representation == ALGORITHM_MINIMUM: 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self._rep = self._data[0] 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru else: 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru # for percentiles, we use the value below which x% of values are 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru # found, which allows for better detection of quantum behaviors. 71363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger if representation == ALGORITHM_MEDIAN: 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru x = int(round(0.5 * self._len + 0.5)) 73363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger elif representation == ALGORITHM_25TH_PERCENTILE: 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru x = int(round(0.25 * self._len + 0.5)) 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru else: 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru raise Exception("invalid representation algorithm %s!" % 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru representation) 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self._rep = self._data[x - 1] 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru def compute(self): 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return self._rep 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 83363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerdef _ParseAndStoreTimes(config_re, time_re, line, bench, dic, 84363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger representation=None): 85363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger """Parses given bench time line with regex and adds data to the given dic. 86363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger config_re: regular expression for parsing the config line. 87363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger time_re: regular expression for parsing bench time. 88363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger line: input string line to parse. 89363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger bench: name of bench for the time values. 90363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger dic: dictionary to store bench values. See bench_dic in parse() below. 91363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger representation: should match one of the ALGORITHM_XXX types.""" 92363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 93363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger for config in re.finditer(config_re, line): 94363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger current_config = config.group(1) 95363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger if config_re.startswith(' tile_'): # per-tile bench, add name prefix 96363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger current_config = 'tile_' + current_config 97363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger times = config.group(2) 98363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger for new_time in re.finditer(time_re, times): 99363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger current_time_type = new_time.group(1) 100363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger iters = [float(i) for i in 101363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger new_time.group(2).strip().split(',')] 102363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger dic.setdefault(bench, {}).setdefault(current_config, {}).setdefault( 103363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger current_time_type, []).append(_ListAlgorithm( 104363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger iters, representation).compute()) 105363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 106363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerdef parse(settings, lines, representation=None): 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru """Parses bench output into a useful data structure. 108363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ({str:str}, __iter__ -> str) -> [BenchDataPoint] 110363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger representation is one of the ALGORITHM_XXX types.""" 111363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru benches = [] 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru current_bench = None 114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger bench_dic = {} # [bench][config][time_type] -> [list of bench values] 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru setting_re = '([^\s=]+)(?:=(\S+))?' 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru settings_re = 'skia bench:((?:\s+' + setting_re + ')*)' 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bench_re = 'running bench (?:\[\d+ \d+\] )?\s*(\S+)' 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru time_re = '(?:(\w*)msecs = )?\s*((?:\d+\.\d+)(?:,\d+\.\d+)*)' 119363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger # non-per-tile benches have configs that don't end with ']' 120363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger config_re = '(\S+[^\]]): ((?:' + time_re + '\s+)+)' 121d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger # per-tile bench lines are in the following format. Note that there are 122d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger # non-averaged bench numbers in separate lines, which we ignore now due to 123d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger # their inaccuracy. 124d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger tile_re = (' tile_(\S+): tile \[\d+,\d+\] out of \[\d+,\d+\] <averaged>:' 125d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger ' ((?:' + time_re + '\s+)+)') 126363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for line in lines: 128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger # see if this line is a settings line 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru settingsMatch = re.search(settings_re, line) 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (settingsMatch): 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru settings = dict(settings) 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for settingMatch in re.finditer(setting_re, settingsMatch.group(1)): 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (settingMatch.group(2)): 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru settings[settingMatch.group(1)] = settingMatch.group(2) 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru else: 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru settings[settingMatch.group(1)] = True 138363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 139363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger # see if this line starts a new bench 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru new_bench = re.search(bench_re, line) 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if new_bench: 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru current_bench = new_bench.group(1) 143363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 144363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger # add configs on this line to the bench_dic 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if current_bench: 146363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger for regex in [config_re, tile_re]: 147363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger _ParseAndStoreTimes(regex, time_re, line, current_bench, 148363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger bench_dic, representation) 149363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 150363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger # append benches to list, use the total time as final bench value. 151363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger for bench in bench_dic: 152363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger for config in bench_dic[bench]: 153363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger for time_type in bench_dic[bench][config]: 154363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger benches.append(BenchDataPoint( 155363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger bench, 156363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger config, 157363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger time_type, 158363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger sum(bench_dic[bench][config][time_type]), 159363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger settings)) 160363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return benches 162363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass LinearRegression: 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru """Linear regression data based on a set of data points. 165363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ([(Number,Number)]) 16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru There must be at least two points for this to make sense.""" 16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru def __init__(self, points): 16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru n = len(points) 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru max_x = Min 17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru min_x = Max 172363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Sx = 0.0 17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Sy = 0.0 17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Sxx = 0.0 17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Sxy = 0.0 17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Syy = 0.0 17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for point in points: 17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru x = point[0] 18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru y = point[1] 18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru max_x = max(max_x, x) 18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru min_x = min(min_x, x) 183363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Sx += x 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Sy += y 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Sxx += x*x 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Sxy += x*y 18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Syy += y*y 189363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru denom = n*Sxx - Sx*Sx 19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (denom != 0.0): 19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru B = (n*Sxy - Sx*Sy) / denom 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru else: 19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru B = 0.0 19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru a = (1.0/n)*(Sy - B*Sx) 196363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru se2 = 0 19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sB2 = 0 19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sa2 = 0 20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (n >= 3 and denom != 0.0): 20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru se2 = (1.0/(n*(n-2)) * (n*Syy - Sy*Sy - B*B*denom)) 20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sB2 = (n*se2) / denom 20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sa2 = sB2 * (1.0/n) * Sxx 204363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 205363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.slope = B 20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.intercept = a 20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.serror = math.sqrt(max(0, se2)) 20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.serror_slope = math.sqrt(max(0, sB2)) 21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.serror_intercept = math.sqrt(max(0, sa2)) 21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.max_x = max_x 21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru self.min_x = min_x 213363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru def __repr__(self): 21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return "LinearRegression(%s, %s, %s, %s, %s)" % ( 21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str(self.slope), 21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str(self.intercept), 21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str(self.serror), 21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str(self.serror_slope), 22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru str(self.serror_intercept), 22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ) 222363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru def find_min_slope(self): 22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru """Finds the minimal slope given one standard deviation.""" 22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru slope = self.slope 22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru intercept = self.intercept 22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru error = self.serror 22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru regr_start = self.min_x 22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru regr_end = self.max_x 23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru regr_width = regr_end - regr_start 231363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if slope < 0: 23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru lower_left_y = slope*regr_start + intercept - error 23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru upper_right_y = slope*regr_end + intercept + error 23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return min(0, (upper_right_y - lower_left_y) / regr_width) 236363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru elif slope > 0: 23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru upper_left_y = slope*regr_start + intercept + error 23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru lower_right_y = slope*regr_end + intercept - error 24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return max(0, (lower_right_y - upper_left_y) / regr_width) 241363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 0 24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudef CreateRevisionLink(revision_number): 24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru """Returns HTML displaying the given revision number and linking to 24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru that revision's change page at code.google.com, e.g. 24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru http://code.google.com/p/skia/source/detail?r=2056 24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru """ 24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return '<a href="http://code.google.com/p/skia/source/detail?r=%s">%s</a>'%( 25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru revision_number, revision_number) 25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querudef main(): 25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru foo = [[0.0, 0.0], [0.0, 1.0], [0.0, 2.0], [0.0, 3.0]] 25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru LinearRegression(foo) 25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruif __name__ == "__main__": 25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru main() 258