info.py revision 1934:84c12fdd57f9
19665Sandreas.hansson@arm.com# Copyright (c) 2003-2004 The Regents of The University of Michigan
29665Sandreas.hansson@arm.com# All rights reserved.
39665Sandreas.hansson@arm.com#
49665Sandreas.hansson@arm.com# Redistribution and use in source and binary forms, with or without
59665Sandreas.hansson@arm.com# modification, are permitted provided that the following conditions are
69665Sandreas.hansson@arm.com# met: redistributions of source code must retain the above copyright
79665Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer;
89665Sandreas.hansson@arm.com# redistributions in binary form must reproduce the above copyright
99665Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer in the
109665Sandreas.hansson@arm.com# documentation and/or other materials provided with the distribution;
119665Sandreas.hansson@arm.com# neither the name of the copyright holders nor the names of its
129665Sandreas.hansson@arm.com# contributors may be used to endorse or promote products derived from
135353Svilas.sridharan@gmail.com# this software without specific prior written permission.
143395Shsul@eecs.umich.edu#
153395Shsul@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
163395Shsul@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
173395Shsul@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
183395Shsul@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
193395Shsul@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
203395Shsul@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
213395Shsul@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
223395Shsul@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
233395Shsul@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
243395Shsul@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
253395Shsul@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
263395Shsul@eecs.umich.edu
273395Shsul@eecs.umich.edufrom __future__ import division
283395Shsul@eecs.umich.eduimport operator, re, types
293395Shsul@eecs.umich.edu
303395Shsul@eecs.umich.edudef unproxy(proxy):
313395Shsul@eecs.umich.edu    if hasattr(proxy, '__unproxy__'):
323395Shsul@eecs.umich.edu        return proxy.__unproxy__()
333395Shsul@eecs.umich.edu
343395Shsul@eecs.umich.edu    return proxy
353395Shsul@eecs.umich.edu
363395Shsul@eecs.umich.edudef scalar(stat):
373395Shsul@eecs.umich.edu    stat = unproxy(stat)
383395Shsul@eecs.umich.edu    assert(stat.__scalar__() != stat.__vector__())
393395Shsul@eecs.umich.edu    return stat.__scalar__()
403395Shsul@eecs.umich.edu
418920Snilay@cs.wisc.edudef vector(stat):
428920Snilay@cs.wisc.edu    stat = unproxy(stat)
438920Snilay@cs.wisc.edu    assert(stat.__scalar__() != stat.__vector__())
448920Snilay@cs.wisc.edu    return stat.__vector__()
457025SBrad.Beckmann@amd.com
469520SAndreas.Sandberg@ARM.comdef value(stat, *args):
479665Sandreas.hansson@arm.com    stat = unproxy(stat)
489520SAndreas.Sandberg@ARM.com    return stat.__value__(*args)
499520SAndreas.Sandberg@ARM.com
509520SAndreas.Sandberg@ARM.comdef values(stat, run):
519520SAndreas.Sandberg@ARM.com    stat = unproxy(stat)
529520SAndreas.Sandberg@ARM.com    result = []
539665Sandreas.hansson@arm.com    for i in xrange(len(stat)):
549665Sandreas.hansson@arm.com        val = value(stat, run, i)
559665Sandreas.hansson@arm.com        if val is None:
569665Sandreas.hansson@arm.com            return None
578920Snilay@cs.wisc.edu        result.append(val)
588920Snilay@cs.wisc.edu    return result
599520SAndreas.Sandberg@ARM.com
609520SAndreas.Sandberg@ARM.comdef total(stat, run):
619520SAndreas.Sandberg@ARM.com    return sum(values(stat, run))
628920Snilay@cs.wisc.edu
639520SAndreas.Sandberg@ARM.comdef len(stat):
648920Snilay@cs.wisc.edu    stat = unproxy(stat)
659665Sandreas.hansson@arm.com    return stat.__len__()
669665Sandreas.hansson@arm.com
679665Sandreas.hansson@arm.comclass Value(object):
689665Sandreas.hansson@arm.com    def __scalar__(self):
699665Sandreas.hansson@arm.com        raise AttributeError, "must define __scalar__ for %s" % (type (self))
709665Sandreas.hansson@arm.com    def __vector__(self):
718920Snilay@cs.wisc.edu        raise AttributeError, "must define __vector__ for %s" % (type (self))
728920Snilay@cs.wisc.edu
738920Snilay@cs.wisc.edu    def __add__(self, other):
748920Snilay@cs.wisc.edu        return BinaryProxy(operator.__add__, self, other)
758920Snilay@cs.wisc.edu    def __sub__(self, other):
769647Sdam.sunwoo@arm.com        return BinaryProxy(operator.__sub__, self, other)
779647Sdam.sunwoo@arm.com    def __mul__(self, other):
789647Sdam.sunwoo@arm.com        return BinaryProxy(operator.__mul__, self, other)
799647Sdam.sunwoo@arm.com    def __div__(self, other):
808920Snilay@cs.wisc.edu        return BinaryProxy(operator.__div__, self, other)
819789Sakash.bagdia@arm.com    def __truediv__(self, other):
829789Sakash.bagdia@arm.com        return BinaryProxy(operator.__truediv__, self, other)
839789Sakash.bagdia@arm.com    def __floordiv__(self, other):
848920Snilay@cs.wisc.edu        return BinaryProxy(operator.__floordiv__, self, other)
858920Snilay@cs.wisc.edu
868920Snilay@cs.wisc.edu    def __radd__(self, other):
878920Snilay@cs.wisc.edu        return BinaryProxy(operator.__add__, other, self)
888920Snilay@cs.wisc.edu    def __rsub__(self, other):
898920Snilay@cs.wisc.edu        return BinaryProxy(operator.__sub__, other, self)
908920Snilay@cs.wisc.edu    def __rmul__(self, other):
918920Snilay@cs.wisc.edu        return BinaryProxy(operator.__mul__, other, self)
928920Snilay@cs.wisc.edu    def __rdiv__(self, other):
938920Snilay@cs.wisc.edu        return BinaryProxy(operator.__div__, other, self)
948920Snilay@cs.wisc.edu    def __rtruediv__(self, other):
958920Snilay@cs.wisc.edu        return BinaryProxy(operator.__truediv__, other, self)
968920Snilay@cs.wisc.edu    def __rfloordiv__(self, other):
979197Snilay@cs.wisc.edu        return BinaryProxy(operator.__floordiv__, other, self)
989197Snilay@cs.wisc.edu
999197Snilay@cs.wisc.edu    def __neg__(self):
1009197Snilay@cs.wisc.edu        return UnaryProxy(operator.__neg__, self)
1019197Snilay@cs.wisc.edu    def __pos__(self):
1023395Shsul@eecs.umich.edu        return UnaryProxy(operator.__pos__, self)
1038920Snilay@cs.wisc.edu    def __abs__(self):
1048920Snilay@cs.wisc.edu        return UnaryProxy(operator.__abs__, self)
1058920Snilay@cs.wisc.edu
1068920Snilay@cs.wisc.educlass Scalar(Value):
1078920Snilay@cs.wisc.edu    def __scalar__(self):
1088920Snilay@cs.wisc.edu        return True
1098920Snilay@cs.wisc.edu
1108920Snilay@cs.wisc.edu    def __vector__(self):
1118920Snilay@cs.wisc.edu        return False
1128920Snilay@cs.wisc.edu
1138920Snilay@cs.wisc.edu    def __value__(self, run):
1148920Snilay@cs.wisc.edu        raise AttributeError, '__value__ must be defined'
1158920Snilay@cs.wisc.edu
1168920Snilay@cs.wisc.educlass VectorItemProxy(Value):
1178920Snilay@cs.wisc.edu    def __init__(self, proxy, index):
1188920Snilay@cs.wisc.edu        self.proxy = proxy
1198920Snilay@cs.wisc.edu        self.index = index
1208920Snilay@cs.wisc.edu
1216776SBrad.Beckmann@amd.com    def __scalar__(self):
1228920Snilay@cs.wisc.edu        return True
1238920Snilay@cs.wisc.edu
1248920Snilay@cs.wisc.edu    def __vector__(self):
1258920Snilay@cs.wisc.edu        return False
1269357Sandreas.hansson@arm.com
1278920Snilay@cs.wisc.edu    def __value__(self, run):
1288920Snilay@cs.wisc.edu        return value(self.proxy, run, self.index)
1298920Snilay@cs.wisc.edu
1308920Snilay@cs.wisc.educlass Vector(Value):
1318920Snilay@cs.wisc.edu    def __scalar__(self):
1328920Snilay@cs.wisc.edu        return False
1338920Snilay@cs.wisc.edu
1348920Snilay@cs.wisc.edu    def __vector__(self):
1358920Snilay@cs.wisc.edu        return True
1368920Snilay@cs.wisc.edu
1378920Snilay@cs.wisc.edu    def __value__(self, run, index):
1388920Snilay@cs.wisc.edu        raise AttributeError, '__value__ must be defined'
1398920Snilay@cs.wisc.edu
1408920Snilay@cs.wisc.edu    def __getitem__(self, index):
1418920Snilay@cs.wisc.edu        return VectorItemProxy(self, index)
1429736Sandreas@sandberg.pp.se
1438920Snilay@cs.wisc.educlass ScalarConstant(Scalar):
1443395Shsul@eecs.umich.edu    def __init__(self, constant):
1455361Srstrong@cs.ucsd.edu        self.constant = constant
1468920Snilay@cs.wisc.edu    def __value__(self, run):
1478920Snilay@cs.wisc.edu        return self.constant
1488920Snilay@cs.wisc.edu
1499151Satgutier@umich.educlass VectorConstant(Vector):
1509151Satgutier@umich.edu    def __init__(self, constant):
1519151Satgutier@umich.edu        self.constant = constant
1529151Satgutier@umich.edu    def __value__(self, run, index):
1539151Satgutier@umich.edu        return self.constant[index]
1549151Satgutier@umich.edu    def __len__(self):
1559562Ssaidi@eecs.umich.edu        return len(self.constant)
1568920Snilay@cs.wisc.edu
1578920Snilay@cs.wisc.edudef WrapValue(value):
1588920Snilay@cs.wisc.edu    if isinstance(value, (int, long, float)):
1598920Snilay@cs.wisc.edu        return ScalarConstant(value)
1608920Snilay@cs.wisc.edu    if isinstance(value, (list, tuple)):
1618920Snilay@cs.wisc.edu        return VectorConstant(value)
1628920Snilay@cs.wisc.edu    if isinstance(value, Value):
1638920Snilay@cs.wisc.edu        return value
1648920Snilay@cs.wisc.edu
1658920Snilay@cs.wisc.edu    raise AttributeError, 'Only values can be wrapped'
1668920Snilay@cs.wisc.edu
1678920Snilay@cs.wisc.educlass Statistic(object):
1688920Snilay@cs.wisc.edu    def __getattr__(self, attr):
1698920Snilay@cs.wisc.edu        if attr in ('data', 'x', 'y'):
1708920Snilay@cs.wisc.edu            result = self.source.data(self, self.bins, self.ticks)
1718920Snilay@cs.wisc.edu            self.data = result.data
1728920Snilay@cs.wisc.edu            self.x = result.x
1738920Snilay@cs.wisc.edu            self.y = result.y
1748920Snilay@cs.wisc.edu        return super(Statistic, self).__getattribute__(attr)
1758920Snilay@cs.wisc.edu
1768920Snilay@cs.wisc.edu    def __setattr__(self, attr, value):
1778920Snilay@cs.wisc.edu        if attr == 'stat':
1788920Snilay@cs.wisc.edu            raise AttributeError, '%s is read only' % stat
1798920Snilay@cs.wisc.edu        if attr in ('source', 'bins', 'ticks'):
1808920Snilay@cs.wisc.edu            if getattr(self, attr) != value:
1818920Snilay@cs.wisc.edu                if hasattr(self, 'data'):
1828920Snilay@cs.wisc.edu                    delattr(self, 'data')
1838920Snilay@cs.wisc.edu
1848920Snilay@cs.wisc.edu        super(Statistic, self).__setattr__(attr, value)
1858920Snilay@cs.wisc.edu
1868920Snilay@cs.wisc.educlass ValueProxy(Value):
1878920Snilay@cs.wisc.edu    def __getattr__(self, attr):
1888920Snilay@cs.wisc.edu        if attr == '__value__':
1898920Snilay@cs.wisc.edu            if scalar(self):
1908920Snilay@cs.wisc.edu                return self.__scalarvalue__
1918920Snilay@cs.wisc.edu            if vector(self):
1928920Snilay@cs.wisc.edu                return self.__vectorvalue__
1938920Snilay@cs.wisc.edu        if attr == '__len__':
1948920Snilay@cs.wisc.edu            if vector(self):
1958920Snilay@cs.wisc.edu                return self.__vectorlen__
1968920Snilay@cs.wisc.edu        return super(ValueProxy, self).__getattribute__(attr)
1978920Snilay@cs.wisc.edu
1988920Snilay@cs.wisc.educlass UnaryProxy(ValueProxy):
1998920Snilay@cs.wisc.edu    def __init__(self, op, arg):
2008920Snilay@cs.wisc.edu        self.op = op
2018920Snilay@cs.wisc.edu        self.arg = WrapValue(arg)
2028920Snilay@cs.wisc.edu
2038920Snilay@cs.wisc.edu    def __scalar__(self):
2048920Snilay@cs.wisc.edu        return scalar(self.arg)
2059539Satgutier@umich.edu
2069539Satgutier@umich.edu    def __vector__(self):
2079539Satgutier@umich.edu        return vector(self.arg)
2088920Snilay@cs.wisc.edu
2098920Snilay@cs.wisc.edu    def __scalarvalue__(self, run):
2108920Snilay@cs.wisc.edu        val = value(self.arg, run)
2118920Snilay@cs.wisc.edu        if val is None:
2128920Snilay@cs.wisc.edu            return None
2138920Snilay@cs.wisc.edu        return self.op(val)
2148920Snilay@cs.wisc.edu
2158920Snilay@cs.wisc.edu    def __vectorvalue__(self, run, index):
2168920Snilay@cs.wisc.edu        val = value(self.arg, run, index)
2178920Snilay@cs.wisc.edu        if val is None:
2188920Snilay@cs.wisc.edu            return None
2198920Snilay@cs.wisc.edu        return self.op(val)
2208956Sjayneel@cs.wisc.edu
2218956Sjayneel@cs.wisc.edu    def __vectorlen__(self):
2228956Sjayneel@cs.wisc.edu        return len(unproxy(self.arg))
2238956Sjayneel@cs.wisc.edu
2248956Sjayneel@cs.wisc.educlass BinaryProxy(ValueProxy):
2258956Sjayneel@cs.wisc.edu    def __init__(self, op, arg0, arg1):
2268956Sjayneel@cs.wisc.edu        super(BinaryProxy, self).__init__()
2278976Sjayneel@cs.wisc.edu        self.op = op
228        self.arg0 = WrapValue(arg0)
229        self.arg1 = WrapValue(arg1)
230
231    def __scalar__(self):
232        return scalar(self.arg0) and scalar(self.arg1)
233
234    def __vector__(self):
235        return vector(self.arg0) or vector(self.arg1)
236
237    def __scalarvalue__(self, run):
238        val0 = value(self.arg0, run)
239        val1 = value(self.arg1, run)
240        if val0 is None or val1 is None:
241            return None
242        return self.op(val0, val1)
243
244    def __vectorvalue__(self, run, index):
245        if scalar(self.arg0):
246            val0 = value(self.arg0, run)
247        if vector(self.arg0):
248            val0 = value(self.arg0, run, index)
249        if scalar(self.arg1):
250            val1 = value(self.arg1, run)
251        if vector(self.arg1):
252            val1 = value(self.arg1, run, index)
253
254        if val0 is None or val1 is None:
255            return None
256
257        return self.op(val0, val1)
258
259    def __vectorlen__(self):
260        if vector(self.arg0) and scalar(self.arg1):
261            return len(self.arg0)
262        if scalar(self.arg0) and vector(self.arg1):
263            return len(self.arg1)
264
265        len0 = len(self.arg0)
266        len1 = len(self.arg1)
267
268        if len0 != len1:
269            raise AttributeError, \
270                  "vectors of different lengths %d != %d" % (len0, len1)
271
272        return len0
273
274class Proxy(Value):
275    def __init__(self, name, dict):
276        self.name = name
277        self.dict = dict
278
279    def __unproxy__(self):
280        return unproxy(self.dict[self.name])
281
282    def __getitem__(self, index):
283        return ItemProxy(self, index)
284
285    def __getattr__(self, attr):
286        return AttrProxy(self, attr)
287
288class ItemProxy(Proxy):
289    def __init__(self, proxy, index):
290        self.proxy = proxy
291        self.index = index
292
293    def __unproxy__(self):
294        return unproxy(unproxy(self.proxy)[self.index])
295
296class AttrProxy(Proxy):
297    def __init__(self, proxy, attr):
298        self.proxy = proxy
299        self.attr = attr
300
301    def __unproxy__(self):
302        return unproxy(getattr(unproxy(self.proxy), self.attr))
303
304class ProxyGroup(object):
305    def __init__(self, dict=None, **kwargs):
306        self.__dict__['dict'] = {}
307
308        if dict is not None:
309            self.dict.update(dict)
310
311        if kwargs:
312            self.dict.update(kwargs)
313
314    def __getattr__(self, name):
315        return Proxy(name, self.dict)
316
317    def __setattr__(self, attr, value):
318        self.dict[attr] = value
319
320class ScalarStat(Statistic,Scalar):
321    def __value__(self, run):
322        if run not in self.data:
323            return None
324        return self.data[run][0][0]
325
326    def display(self, run=None):
327        import display
328        p = display.Print()
329        p.name = self.name
330        p.desc = self.desc
331        p.value = value(self, run)
332        p.flags = self.flags
333        p.precision = self.precision
334        if display.all or (self.flags & flags.printable):
335            p.display()
336
337class VectorStat(Statistic,Vector):
338    def __value__(self, run, item):
339        if run not in self.data:
340            return None
341        return self.data[run][item][0]
342
343    def __len__(self):
344        return self.x
345
346    def display(self, run=None):
347        import display
348        d = display.VectorDisplay()
349        d.name = self.name
350        d.desc = self.desc
351        d.value = [ value(self, run, i) for i in xrange(len(self)) ]
352        d.flags = self.flags
353        d.precision = self.precision
354        d.display()
355
356class Formula(Value):
357    def __getattribute__(self, attr):
358        if attr not in ( '__scalar__', '__vector__', '__value__', '__len__' ):
359            return super(Formula, self).__getattribute__(attr)
360
361        formula = re.sub(':', '__', self.formula)
362        value = eval(formula, self.source.stattop)
363        return getattr(value, attr)
364
365class SimpleDist(Statistic):
366    def __init__(self, sums, squares, samples):
367        self.sums = sums
368        self.squares = squares
369        self.samples = samples
370
371    def display(self, name, desc, flags, precision):
372        import display
373        p = display.Print()
374        p.flags = flags
375        p.precision = precision
376
377        if self.samples > 0:
378            p.name = name + ".mean"
379            p.value = self.sums / self.samples
380            p.display()
381
382            p.name = name + ".stdev"
383            if self.samples > 1:
384                var = (self.samples * self.squares - self.sums ** 2) \
385                      / (self.samples * (self.samples - 1))
386                if var >= 0:
387                    p.value = math.sqrt(var)
388                else:
389                    p.value = 'NaN'
390            else:
391                p.value = 0.0
392            p.display()
393
394        p.name = name + ".samples"
395        p.value = self.samples
396        p.display()
397
398    def comparable(self, other):
399        return True
400
401    def __eq__(self, other):
402        return self.sums == other.sums and self.squares == other.squares and \
403               self.samples == other.samples
404
405    def __isub__(self, other):
406        self.sums -= other.sums
407        self.squares -= other.squares
408        self.samples -= other.samples
409        return self
410
411    def __iadd__(self, other):
412        self.sums += other.sums
413        self.squares += other.squares
414        self.samples += other.samples
415        return self
416
417    def __itruediv__(self, other):
418        if not other:
419            return self
420        self.sums /= other
421        self.squares /= other
422        self.samples /= other
423        return self
424
425class FullDist(SimpleDist):
426    def __init__(self, sums, squares, samples, minval, maxval,
427                 under, vec, over, min, max, bsize, size):
428        self.sums = sums
429        self.squares = squares
430        self.samples = samples
431        self.minval = minval
432        self.maxval = maxval
433        self.under = under
434        self.vec = vec
435        self.over = over
436        self.min = min
437        self.max = max
438        self.bsize = bsize
439        self.size = size
440
441    def display(self, name, desc, flags, precision):
442        import display
443        p = display.Print()
444        p.flags = flags
445        p.precision = precision
446
447        p.name = name + '.min_val'
448        p.value = self.minval
449        p.display()
450
451        p.name = name + '.max_val'
452        p.value = self.maxval
453        p.display()
454
455        p.name = name + '.underflow'
456        p.value = self.under
457        p.display()
458
459        i = self.min
460        for val in self.vec[:-1]:
461            p.name = name + '[%d:%d]' % (i, i + self.bsize - 1)
462            p.value = val
463            p.display()
464            i += self.bsize
465
466        p.name = name + '[%d:%d]' % (i, self.max)
467        p.value = self.vec[-1]
468        p.display()
469
470
471        p.name = name + '.overflow'
472        p.value = self.over
473        p.display()
474
475        SimpleDist.display(self, name, desc, flags, precision)
476
477    def comparable(self, other):
478        return self.min == other.min and self.max == other.max and \
479               self.bsize == other.bsize and self.size == other.size
480
481    def __eq__(self, other):
482        return self.sums == other.sums and self.squares == other.squares and \
483               self.samples == other.samples
484
485    def __isub__(self, other):
486        self.sums -= other.sums
487        self.squares -= other.squares
488        self.samples -= other.samples
489
490        if other.samples:
491            self.minval = min(self.minval, other.minval)
492            self.maxval = max(self.maxval, other.maxval)
493            self.under -= under
494            self.vec = map(lambda x,y: x - y, self.vec, other.vec)
495            self.over -= over
496        return self
497
498    def __iadd__(self, other):
499        if not self.samples and other.samples:
500            self = other
501            return self
502
503        self.sums += other.sums
504        self.squares += other.squares
505        self.samples += other.samples
506
507        if other.samples:
508            self.minval = min(self.minval, other.minval)
509            self.maxval = max(self.maxval, other.maxval)
510            self.under += other.under
511            self.vec = map(lambda x,y: x + y, self.vec, other.vec)
512            self.over += other.over
513        return self
514
515    def __itruediv__(self, other):
516        if not other:
517            return self
518        self.sums /= other
519        self.squares /= other
520        self.samples /= other
521
522        if self.samples:
523            self.under /= other
524            for i in xrange(len(self.vec)):
525                self.vec[i] /= other
526            self.over /= other
527        return self
528
529class Dist(Statistic):
530    def display(self):
531        import display
532        if not display.all and not (self.flags & flags.printable):
533            return
534
535        self.dist.display(self.name, self.desc, self.flags, self.precision)
536
537    def comparable(self, other):
538        return self.name == other.name and \
539               self.dist.compareable(other.dist)
540
541    def __eq__(self, other):
542        return self.dist == other.dist
543
544    def __isub__(self, other):
545        self.dist -= other.dist
546        return self
547
548    def __iadd__(self, other):
549        self.dist += other.dist
550        return self
551
552    def __itruediv__(self, other):
553        if not other:
554            return self
555        self.dist /= other
556        return self
557
558class VectorDist(Statistic):
559    def display(self):
560        import display
561        if not display.all and not (self.flags & flags.printable):
562            return
563
564        if isinstance(self.dist, SimpleDist):
565            return
566
567        for dist,sn,sd,i in map(None, self.dist, self.subnames, self.subdescs,
568                                range(len(self.dist))):
569            if len(sn) > 0:
570                name = '%s.%s' % (self.name, sn)
571            else:
572                name = '%s[%d]' % (self.name, i)
573
574            if len(sd) > 0:
575                desc = sd
576            else:
577                desc = self.desc
578
579            dist.display(name, desc, self.flags, self.precision)
580
581        if (self.flags & flags.total) or 1:
582            if isinstance(self.dist[0], SimpleDist):
583                disttotal = SimpleDist( \
584                    reduce(sums, [d.sums for d in self.dist]),
585                    reduce(sums, [d.squares for d in self.dist]),
586                    reduce(sums, [d.samples for d in self.dist]))
587            else:
588                disttotal = FullDist( \
589                    reduce(sums, [d.sums for d in self.dist]),
590                    reduce(sums, [d.squares for d in self.dist]),
591                    reduce(sums, [d.samples for d in self.dist]),
592                    min([d.minval for d in self.dist]),
593                    max([d.maxval for d in self.dist]),
594                    reduce(sums, [d.under for d in self.dist]),
595                    reduce(sums, [d.vec for d in self.dist]),
596                    reduce(sums, [d.over for d in self.dist]),
597                    dist[0].min,
598                    dist[0].max,
599                    dist[0].bsize,
600                    dist[0].size)
601
602            name = '%s.total' % (self.name)
603            desc = self.desc
604            disttotal.display(name, desc, self.flags, self.precision)
605
606    def comparable(self, other):
607        return self.name == other.name and \
608               alltrue(map(lambda x, y : x.comparable(y),
609                           self.dist,
610                           other.dist))
611
612    def __eq__(self, other):
613        return alltrue(map(lambda x, y : x == y, self.dist, other.dist))
614
615    def __isub__(self, other):
616        if isinstance(self.dist, (list, tuple)) and \
617               isinstance(other.dist, (list, tuple)):
618            for sd,od in zip(self.dist, other.dist):
619                sd -= od
620        else:
621            self.dist -= other.dist
622        return self
623
624    def __iadd__(self, other):
625        if isinstance(self.dist, (list, tuple)) and \
626               isinstance(other.dist, (list, tuple)):
627            for sd,od in zip(self.dist, other.dist):
628                sd += od
629        else:
630            self.dist += other.dist
631        return self
632
633    def __itruediv__(self, other):
634        if not other:
635            return self
636        if isinstance(self.dist, (list, tuple)):
637            for dist in self.dist:
638                dist /= other
639        else:
640            self.dist /= other
641        return self
642
643class Vector2d(Statistic):
644    def display(self):
645        import display
646        if not display.all and not (self.flags & flags.printable):
647            return
648
649        d = display.VectorDisplay()
650        d.__dict__.update(self.__dict__)
651
652        if self.__dict__.has_key('ysubnames'):
653            ysubnames = list(self.ysubnames)
654            slack = self.x - len(ysubnames)
655            if slack > 0:
656                ysubnames.extend(['']*slack)
657        else:
658            ysubnames = range(self.x)
659
660        for x,sname in enumerate(ysubnames):
661            o = x * self.y
662            d.value = self.value[o:o+self.y]
663            d.name = '%s[%s]' % (self.name, sname)
664            d.display()
665
666        if self.flags & flags.total:
667            d.value = []
668            for y in range(self.y):
669                xtot = 0.0
670                for x in range(self.x):
671                    xtot += self.value[y + x * self.x]
672                d.value.append(xtot)
673
674            d.name = self.name + '.total'
675            d.display()
676
677    def comparable(self, other):
678        return self.name == other.name and self.x == other.x and \
679               self.y == other.y
680
681    def __eq__(self, other):
682        return True
683
684    def __isub__(self, other):
685        return self
686
687    def __iadd__(self, other):
688        return self
689
690    def __itruediv__(self, other):
691        if not other:
692            return self
693        return self
694
695def NewStat(source, data):
696    stat = None
697    if data.type == 'SCALAR':
698        stat = ScalarStat()
699    elif data.type == 'VECTOR':
700        stat = VectorStat()
701    elif data.type == 'DIST':
702        stat = Dist()
703    elif data.type == 'VECTORDIST':
704        stat = VectorDist()
705    elif data.type == 'VECTOR2D':
706        stat = Vector2d()
707    elif data.type == 'FORMULA':
708        stat = Formula()
709
710    stat.__dict__['source'] = source
711    stat.__dict__['bins'] = None
712    stat.__dict__['ticks'] = None
713    stat.__dict__.update(data.__dict__)
714
715    return stat
716
717