11758Ssaidi@eecs.umich.edu# Copyright (c) 2003-2004 The Regents of The University of Michigan
21758Ssaidi@eecs.umich.edu# All rights reserved.
31758Ssaidi@eecs.umich.edu#
41758Ssaidi@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
51758Ssaidi@eecs.umich.edu# modification, are permitted provided that the following conditions are
61758Ssaidi@eecs.umich.edu# met: redistributions of source code must retain the above copyright
71758Ssaidi@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
81758Ssaidi@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
91758Ssaidi@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
101758Ssaidi@eecs.umich.edu# documentation and/or other materials provided with the distribution;
111758Ssaidi@eecs.umich.edu# neither the name of the copyright holders nor the names of its
121758Ssaidi@eecs.umich.edu# contributors may be used to endorse or promote products derived from
131758Ssaidi@eecs.umich.edu# this software without specific prior written permission.
141758Ssaidi@eecs.umich.edu#
151758Ssaidi@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
161758Ssaidi@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
171758Ssaidi@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
181758Ssaidi@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
191758Ssaidi@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
201758Ssaidi@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
211758Ssaidi@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
221758Ssaidi@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
231758Ssaidi@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
241758Ssaidi@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
251758Ssaidi@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262665Ssaidi@eecs.umich.edu#
272665Ssaidi@eecs.umich.edu# Authors: Nathan Binkert
281758Ssaidi@eecs.umich.edu
291049Sbinkertn@umich.edufrom __future__ import division
301049Sbinkertn@umich.eduimport operator, re, types
311049Sbinkertn@umich.edu
322015Sbinkertn@umich.educlass ProxyError(Exception):
332015Sbinkertn@umich.edu    pass
342015Sbinkertn@umich.edu
351929Sbinkertn@umich.edudef unproxy(proxy):
361929Sbinkertn@umich.edu    if hasattr(proxy, '__unproxy__'):
371929Sbinkertn@umich.edu        return proxy.__unproxy__()
381049Sbinkertn@umich.edu
391929Sbinkertn@umich.edu    return proxy
401049Sbinkertn@umich.edu
411929Sbinkertn@umich.edudef scalar(stat):
421929Sbinkertn@umich.edu    stat = unproxy(stat)
431929Sbinkertn@umich.edu    assert(stat.__scalar__() != stat.__vector__())
441929Sbinkertn@umich.edu    return stat.__scalar__()
451049Sbinkertn@umich.edu
461929Sbinkertn@umich.edudef vector(stat):
471929Sbinkertn@umich.edu    stat = unproxy(stat)
481929Sbinkertn@umich.edu    assert(stat.__scalar__() != stat.__vector__())
491929Sbinkertn@umich.edu    return stat.__vector__()
501049Sbinkertn@umich.edu
511929Sbinkertn@umich.edudef value(stat, *args):
521929Sbinkertn@umich.edu    stat = unproxy(stat)
531929Sbinkertn@umich.edu    return stat.__value__(*args)
541049Sbinkertn@umich.edu
551929Sbinkertn@umich.edudef values(stat, run):
561929Sbinkertn@umich.edu    stat = unproxy(stat)
571929Sbinkertn@umich.edu    result = []
581929Sbinkertn@umich.edu    for i in xrange(len(stat)):
591934Sbinkertn@umich.edu        val = value(stat, run, i)
601929Sbinkertn@umich.edu        if val is None:
611929Sbinkertn@umich.edu            return None
621929Sbinkertn@umich.edu        result.append(val)
631049Sbinkertn@umich.edu    return result
641049Sbinkertn@umich.edu
651929Sbinkertn@umich.edudef total(stat, run):
661929Sbinkertn@umich.edu    return sum(values(stat, run))
671049Sbinkertn@umich.edu
681929Sbinkertn@umich.edudef len(stat):
691929Sbinkertn@umich.edu    stat = unproxy(stat)
701929Sbinkertn@umich.edu    return stat.__len__()
711049Sbinkertn@umich.edu
721929Sbinkertn@umich.educlass Value(object):
731929Sbinkertn@umich.edu    def __scalar__(self):
741929Sbinkertn@umich.edu        raise AttributeError, "must define __scalar__ for %s" % (type (self))
751929Sbinkertn@umich.edu    def __vector__(self):
761929Sbinkertn@umich.edu        raise AttributeError, "must define __vector__ for %s" % (type (self))
771049Sbinkertn@umich.edu
781929Sbinkertn@umich.edu    def __add__(self, other):
791929Sbinkertn@umich.edu        return BinaryProxy(operator.__add__, self, other)
801929Sbinkertn@umich.edu    def __sub__(self, other):
811929Sbinkertn@umich.edu        return BinaryProxy(operator.__sub__, self, other)
821929Sbinkertn@umich.edu    def __mul__(self, other):
831929Sbinkertn@umich.edu        return BinaryProxy(operator.__mul__, self, other)
841929Sbinkertn@umich.edu    def __div__(self, other):
851929Sbinkertn@umich.edu        return BinaryProxy(operator.__div__, self, other)
861929Sbinkertn@umich.edu    def __truediv__(self, other):
871929Sbinkertn@umich.edu        return BinaryProxy(operator.__truediv__, self, other)
881929Sbinkertn@umich.edu    def __floordiv__(self, other):
891929Sbinkertn@umich.edu        return BinaryProxy(operator.__floordiv__, self, other)
901049Sbinkertn@umich.edu
911929Sbinkertn@umich.edu    def __radd__(self, other):
921929Sbinkertn@umich.edu        return BinaryProxy(operator.__add__, other, self)
931929Sbinkertn@umich.edu    def __rsub__(self, other):
941929Sbinkertn@umich.edu        return BinaryProxy(operator.__sub__, other, self)
951929Sbinkertn@umich.edu    def __rmul__(self, other):
961929Sbinkertn@umich.edu        return BinaryProxy(operator.__mul__, other, self)
971929Sbinkertn@umich.edu    def __rdiv__(self, other):
981929Sbinkertn@umich.edu        return BinaryProxy(operator.__div__, other, self)
991929Sbinkertn@umich.edu    def __rtruediv__(self, other):
1001929Sbinkertn@umich.edu        return BinaryProxy(operator.__truediv__, other, self)
1011929Sbinkertn@umich.edu    def __rfloordiv__(self, other):
1021929Sbinkertn@umich.edu        return BinaryProxy(operator.__floordiv__, other, self)
1031929Sbinkertn@umich.edu
1041929Sbinkertn@umich.edu    def __neg__(self):
1051929Sbinkertn@umich.edu        return UnaryProxy(operator.__neg__, self)
1061929Sbinkertn@umich.edu    def __pos__(self):
1071929Sbinkertn@umich.edu        return UnaryProxy(operator.__pos__, self)
1081929Sbinkertn@umich.edu    def __abs__(self):
1091929Sbinkertn@umich.edu        return UnaryProxy(operator.__abs__, self)
1101929Sbinkertn@umich.edu
1111929Sbinkertn@umich.educlass Scalar(Value):
1121929Sbinkertn@umich.edu    def __scalar__(self):
1131929Sbinkertn@umich.edu        return True
1141929Sbinkertn@umich.edu
1151929Sbinkertn@umich.edu    def __vector__(self):
1161929Sbinkertn@umich.edu        return False
1171929Sbinkertn@umich.edu
1181929Sbinkertn@umich.edu    def __value__(self, run):
1191929Sbinkertn@umich.edu        raise AttributeError, '__value__ must be defined'
1201929Sbinkertn@umich.edu
1211929Sbinkertn@umich.educlass VectorItemProxy(Value):
1221929Sbinkertn@umich.edu    def __init__(self, proxy, index):
1231929Sbinkertn@umich.edu        self.proxy = proxy
1241929Sbinkertn@umich.edu        self.index = index
1251929Sbinkertn@umich.edu
1261929Sbinkertn@umich.edu    def __scalar__(self):
1271929Sbinkertn@umich.edu        return True
1281929Sbinkertn@umich.edu
1291929Sbinkertn@umich.edu    def __vector__(self):
1301929Sbinkertn@umich.edu        return False
1311929Sbinkertn@umich.edu
1321929Sbinkertn@umich.edu    def __value__(self, run):
1331929Sbinkertn@umich.edu        return value(self.proxy, run, self.index)
1341929Sbinkertn@umich.edu
1351929Sbinkertn@umich.educlass Vector(Value):
1361929Sbinkertn@umich.edu    def __scalar__(self):
1371929Sbinkertn@umich.edu        return False
1381929Sbinkertn@umich.edu
1391929Sbinkertn@umich.edu    def __vector__(self):
1401929Sbinkertn@umich.edu        return True
1411929Sbinkertn@umich.edu
1421929Sbinkertn@umich.edu    def __value__(self, run, index):
1431929Sbinkertn@umich.edu        raise AttributeError, '__value__ must be defined'
1441929Sbinkertn@umich.edu
1451929Sbinkertn@umich.edu    def __getitem__(self, index):
1461929Sbinkertn@umich.edu        return VectorItemProxy(self, index)
1471929Sbinkertn@umich.edu
1481929Sbinkertn@umich.educlass ScalarConstant(Scalar):
1491929Sbinkertn@umich.edu    def __init__(self, constant):
1501929Sbinkertn@umich.edu        self.constant = constant
1511929Sbinkertn@umich.edu    def __value__(self, run):
1521929Sbinkertn@umich.edu        return self.constant
1531986Sbinkertn@umich.edu    def __str__(self):
1541986Sbinkertn@umich.edu        return str(self.constant)
1551929Sbinkertn@umich.edu
1561929Sbinkertn@umich.educlass VectorConstant(Vector):
1571929Sbinkertn@umich.edu    def __init__(self, constant):
1581929Sbinkertn@umich.edu        self.constant = constant
1591929Sbinkertn@umich.edu    def __value__(self, run, index):
1601929Sbinkertn@umich.edu        return self.constant[index]
1611929Sbinkertn@umich.edu    def __len__(self):
1621929Sbinkertn@umich.edu        return len(self.constant)
1631986Sbinkertn@umich.edu    def __str__(self):
1641986Sbinkertn@umich.edu        return str(self.constant)
1651929Sbinkertn@umich.edu
1661929Sbinkertn@umich.edudef WrapValue(value):
1671929Sbinkertn@umich.edu    if isinstance(value, (int, long, float)):
1681929Sbinkertn@umich.edu        return ScalarConstant(value)
1691929Sbinkertn@umich.edu    if isinstance(value, (list, tuple)):
1701929Sbinkertn@umich.edu        return VectorConstant(value)
1711929Sbinkertn@umich.edu    if isinstance(value, Value):
1721929Sbinkertn@umich.edu        return value
1731929Sbinkertn@umich.edu
1741929Sbinkertn@umich.edu    raise AttributeError, 'Only values can be wrapped'
1751049Sbinkertn@umich.edu
1761049Sbinkertn@umich.educlass Statistic(object):
1771929Sbinkertn@umich.edu    def __getattr__(self, attr):
1781929Sbinkertn@umich.edu        if attr in ('data', 'x', 'y'):
1792343Sbinkertn@umich.edu            result = self.source.data(self, self.ticks)
1801929Sbinkertn@umich.edu            self.data = result.data
1811929Sbinkertn@umich.edu            self.x = result.x
1821929Sbinkertn@umich.edu            self.y = result.y
1831929Sbinkertn@umich.edu        return super(Statistic, self).__getattribute__(attr)
1841049Sbinkertn@umich.edu
1851049Sbinkertn@umich.edu    def __setattr__(self, attr, value):
1861929Sbinkertn@umich.edu        if attr == 'stat':
1871929Sbinkertn@umich.edu            raise AttributeError, '%s is read only' % stat
1882343Sbinkertn@umich.edu        if attr in ('source', 'ticks'):
1891929Sbinkertn@umich.edu            if getattr(self, attr) != value:
1901929Sbinkertn@umich.edu                if hasattr(self, 'data'):
1911929Sbinkertn@umich.edu                    delattr(self, 'data')
1921049Sbinkertn@umich.edu
1931929Sbinkertn@umich.edu        super(Statistic, self).__setattr__(attr, value)
1941049Sbinkertn@umich.edu
1951986Sbinkertn@umich.edu    def __str__(self):
1961986Sbinkertn@umich.edu        return self.name
1971986Sbinkertn@umich.edu
1981929Sbinkertn@umich.educlass ValueProxy(Value):
1991929Sbinkertn@umich.edu    def __getattr__(self, attr):
2001929Sbinkertn@umich.edu        if attr == '__value__':
2011929Sbinkertn@umich.edu            if scalar(self):
2021929Sbinkertn@umich.edu                return self.__scalarvalue__
2031929Sbinkertn@umich.edu            if vector(self):
2041929Sbinkertn@umich.edu                return self.__vectorvalue__
2051929Sbinkertn@umich.edu        if attr == '__len__':
2061929Sbinkertn@umich.edu            if vector(self):
2071929Sbinkertn@umich.edu                return self.__vectorlen__
2081929Sbinkertn@umich.edu        return super(ValueProxy, self).__getattribute__(attr)
2091049Sbinkertn@umich.edu
2101929Sbinkertn@umich.educlass UnaryProxy(ValueProxy):
2111929Sbinkertn@umich.edu    def __init__(self, op, arg):
2121929Sbinkertn@umich.edu        self.op = op
2131929Sbinkertn@umich.edu        self.arg = WrapValue(arg)
2141049Sbinkertn@umich.edu
2151929Sbinkertn@umich.edu    def __scalar__(self):
2161929Sbinkertn@umich.edu        return scalar(self.arg)
2171049Sbinkertn@umich.edu
2181929Sbinkertn@umich.edu    def __vector__(self):
2191929Sbinkertn@umich.edu        return vector(self.arg)
2201049Sbinkertn@umich.edu
2211929Sbinkertn@umich.edu    def __scalarvalue__(self, run):
2221929Sbinkertn@umich.edu        val = value(self.arg, run)
2231929Sbinkertn@umich.edu        if val is None:
2241929Sbinkertn@umich.edu            return None
2251929Sbinkertn@umich.edu        return self.op(val)
2261049Sbinkertn@umich.edu
2271929Sbinkertn@umich.edu    def __vectorvalue__(self, run, index):
2281929Sbinkertn@umich.edu        val = value(self.arg, run, index)
2291929Sbinkertn@umich.edu        if val is None:
2301929Sbinkertn@umich.edu            return None
2311929Sbinkertn@umich.edu        return self.op(val)
2321049Sbinkertn@umich.edu
2331929Sbinkertn@umich.edu    def __vectorlen__(self):
2341929Sbinkertn@umich.edu        return len(unproxy(self.arg))
2351049Sbinkertn@umich.edu
2361986Sbinkertn@umich.edu    def __str__(self):
2371986Sbinkertn@umich.edu        if self.op == operator.__neg__:
2381986Sbinkertn@umich.edu            return '-%s' % str(self.arg)
2391986Sbinkertn@umich.edu        if self.op == operator.__pos__:
2401986Sbinkertn@umich.edu            return '+%s' % str(self.arg)
2411986Sbinkertn@umich.edu        if self.op == operator.__abs__:
2421986Sbinkertn@umich.edu            return 'abs(%s)' % self.arg
2431986Sbinkertn@umich.edu
2441929Sbinkertn@umich.educlass BinaryProxy(ValueProxy):
2451929Sbinkertn@umich.edu    def __init__(self, op, arg0, arg1):
2461929Sbinkertn@umich.edu        super(BinaryProxy, self).__init__()
2471929Sbinkertn@umich.edu        self.op = op
2481929Sbinkertn@umich.edu        self.arg0 = WrapValue(arg0)
2491929Sbinkertn@umich.edu        self.arg1 = WrapValue(arg1)
2501049Sbinkertn@umich.edu
2511929Sbinkertn@umich.edu    def __scalar__(self):
2521929Sbinkertn@umich.edu        return scalar(self.arg0) and scalar(self.arg1)
2531049Sbinkertn@umich.edu
2541929Sbinkertn@umich.edu    def __vector__(self):
2551929Sbinkertn@umich.edu        return vector(self.arg0) or vector(self.arg1)
2561929Sbinkertn@umich.edu
2571929Sbinkertn@umich.edu    def __scalarvalue__(self, run):
2581929Sbinkertn@umich.edu        val0 = value(self.arg0, run)
2591929Sbinkertn@umich.edu        val1 = value(self.arg1, run)
2601929Sbinkertn@umich.edu        if val0 is None or val1 is None:
2611929Sbinkertn@umich.edu            return None
2621987Sbinkertn@umich.edu        try:
2631987Sbinkertn@umich.edu            return self.op(val0, val1)
2641987Sbinkertn@umich.edu        except ZeroDivisionError:
2651987Sbinkertn@umich.edu            return None
2661929Sbinkertn@umich.edu
2671929Sbinkertn@umich.edu    def __vectorvalue__(self, run, index):
2681929Sbinkertn@umich.edu        if scalar(self.arg0):
2691929Sbinkertn@umich.edu            val0 = value(self.arg0, run)
2701929Sbinkertn@umich.edu        if vector(self.arg0):
2711929Sbinkertn@umich.edu            val0 = value(self.arg0, run, index)
2721929Sbinkertn@umich.edu        if scalar(self.arg1):
2731929Sbinkertn@umich.edu            val1 = value(self.arg1, run)
2741929Sbinkertn@umich.edu        if vector(self.arg1):
2751929Sbinkertn@umich.edu            val1 = value(self.arg1, run, index)
2761929Sbinkertn@umich.edu
2771929Sbinkertn@umich.edu        if val0 is None or val1 is None:
2781929Sbinkertn@umich.edu            return None
2791929Sbinkertn@umich.edu
2801987Sbinkertn@umich.edu        try:
2811987Sbinkertn@umich.edu            return self.op(val0, val1)
2821987Sbinkertn@umich.edu        except ZeroDivisionError:
2831987Sbinkertn@umich.edu            return None
2841929Sbinkertn@umich.edu
2851929Sbinkertn@umich.edu    def __vectorlen__(self):
2861929Sbinkertn@umich.edu        if vector(self.arg0) and scalar(self.arg1):
2871929Sbinkertn@umich.edu            return len(self.arg0)
2881929Sbinkertn@umich.edu        if scalar(self.arg0) and vector(self.arg1):
2891929Sbinkertn@umich.edu            return len(self.arg1)
2901929Sbinkertn@umich.edu
2911929Sbinkertn@umich.edu        len0 = len(self.arg0)
2921929Sbinkertn@umich.edu        len1 = len(self.arg1)
2931929Sbinkertn@umich.edu
2941929Sbinkertn@umich.edu        if len0 != len1:
2951929Sbinkertn@umich.edu            raise AttributeError, \
2961929Sbinkertn@umich.edu                  "vectors of different lengths %d != %d" % (len0, len1)
2971929Sbinkertn@umich.edu
2981929Sbinkertn@umich.edu        return len0
2991929Sbinkertn@umich.edu
3001986Sbinkertn@umich.edu    def __str__(self):
3011986Sbinkertn@umich.edu        ops = { operator.__add__ : '+',
3021986Sbinkertn@umich.edu                operator.__sub__ : '-',
3031986Sbinkertn@umich.edu                operator.__mul__ : '*',
3041986Sbinkertn@umich.edu                operator.__div__ : '/',
3051986Sbinkertn@umich.edu                operator.__truediv__ : '/',
3061986Sbinkertn@umich.edu                operator.__floordiv__ : '//' }
3071986Sbinkertn@umich.edu
3081986Sbinkertn@umich.edu        return '(%s %s %s)' % (str(self.arg0), ops[self.op], str(self.arg1))
3091986Sbinkertn@umich.edu
3101929Sbinkertn@umich.educlass Proxy(Value):
3111929Sbinkertn@umich.edu    def __init__(self, name, dict):
3121929Sbinkertn@umich.edu        self.name = name
3131929Sbinkertn@umich.edu        self.dict = dict
3141929Sbinkertn@umich.edu
3151929Sbinkertn@umich.edu    def __unproxy__(self):
3161929Sbinkertn@umich.edu        return unproxy(self.dict[self.name])
3171929Sbinkertn@umich.edu
3181929Sbinkertn@umich.edu    def __getitem__(self, index):
3191929Sbinkertn@umich.edu        return ItemProxy(self, index)
3201929Sbinkertn@umich.edu
3211929Sbinkertn@umich.edu    def __getattr__(self, attr):
3221929Sbinkertn@umich.edu        return AttrProxy(self, attr)
3231929Sbinkertn@umich.edu
3241986Sbinkertn@umich.edu    def __str__(self):
3251986Sbinkertn@umich.edu        return str(self.dict[self.name])
3261986Sbinkertn@umich.edu
3271929Sbinkertn@umich.educlass ItemProxy(Proxy):
3281929Sbinkertn@umich.edu    def __init__(self, proxy, index):
3291929Sbinkertn@umich.edu        self.proxy = proxy
3301929Sbinkertn@umich.edu        self.index = index
3311929Sbinkertn@umich.edu
3321929Sbinkertn@umich.edu    def __unproxy__(self):
3331929Sbinkertn@umich.edu        return unproxy(unproxy(self.proxy)[self.index])
3341929Sbinkertn@umich.edu
3351986Sbinkertn@umich.edu    def __str__(self):
3361986Sbinkertn@umich.edu        return '%s[%s]' % (self.proxy, self.index)
3371986Sbinkertn@umich.edu
3381929Sbinkertn@umich.educlass AttrProxy(Proxy):
3391929Sbinkertn@umich.edu    def __init__(self, proxy, attr):
3401929Sbinkertn@umich.edu        self.proxy = proxy
3411929Sbinkertn@umich.edu        self.attr = attr
3421929Sbinkertn@umich.edu
3431929Sbinkertn@umich.edu    def __unproxy__(self):
3442015Sbinkertn@umich.edu        proxy = unproxy(self.proxy)
3452015Sbinkertn@umich.edu        try:
3462015Sbinkertn@umich.edu            attr = getattr(proxy, self.attr)
3472015Sbinkertn@umich.edu        except AttributeError, e:
3482015Sbinkertn@umich.edu            raise ProxyError, e
3492015Sbinkertn@umich.edu        return unproxy(attr)
3501929Sbinkertn@umich.edu
3511986Sbinkertn@umich.edu    def __str__(self):
3521986Sbinkertn@umich.edu        return '%s.%s' % (self.proxy, self.attr)
3531986Sbinkertn@umich.edu
3541929Sbinkertn@umich.educlass ProxyGroup(object):
3551929Sbinkertn@umich.edu    def __init__(self, dict=None, **kwargs):
3561929Sbinkertn@umich.edu        self.__dict__['dict'] = {}
3571929Sbinkertn@umich.edu
3581929Sbinkertn@umich.edu        if dict is not None:
3591929Sbinkertn@umich.edu            self.dict.update(dict)
3601929Sbinkertn@umich.edu
3611929Sbinkertn@umich.edu        if kwargs:
3621929Sbinkertn@umich.edu            self.dict.update(kwargs)
3631929Sbinkertn@umich.edu
3641929Sbinkertn@umich.edu    def __getattr__(self, name):
3651929Sbinkertn@umich.edu        return Proxy(name, self.dict)
3661929Sbinkertn@umich.edu
3671929Sbinkertn@umich.edu    def __setattr__(self, attr, value):
3681929Sbinkertn@umich.edu        self.dict[attr] = value
3691929Sbinkertn@umich.edu
3701929Sbinkertn@umich.educlass ScalarStat(Statistic,Scalar):
3711929Sbinkertn@umich.edu    def __value__(self, run):
3721929Sbinkertn@umich.edu        if run not in self.data:
3731929Sbinkertn@umich.edu            return None
3741929Sbinkertn@umich.edu        return self.data[run][0][0]
3751929Sbinkertn@umich.edu
3761929Sbinkertn@umich.edu    def display(self, run=None):
3771049Sbinkertn@umich.edu        import display
3781049Sbinkertn@umich.edu        p = display.Print()
3791049Sbinkertn@umich.edu        p.name = self.name
3801049Sbinkertn@umich.edu        p.desc = self.desc
3811929Sbinkertn@umich.edu        p.value = value(self, run)
3821049Sbinkertn@umich.edu        p.flags = self.flags
3831049Sbinkertn@umich.edu        p.precision = self.precision
3841049Sbinkertn@umich.edu        if display.all or (self.flags & flags.printable):
3851049Sbinkertn@umich.edu            p.display()
3861049Sbinkertn@umich.edu
3871929Sbinkertn@umich.educlass VectorStat(Statistic,Vector):
3881929Sbinkertn@umich.edu    def __value__(self, run, item):
3891929Sbinkertn@umich.edu        if run not in self.data:
3901929Sbinkertn@umich.edu            return None
3911929Sbinkertn@umich.edu        return self.data[run][item][0]
3921049Sbinkertn@umich.edu
3931929Sbinkertn@umich.edu    def __len__(self):
3941929Sbinkertn@umich.edu        return self.x
3951049Sbinkertn@umich.edu
3961929Sbinkertn@umich.edu    def display(self, run=None):
3971049Sbinkertn@umich.edu        import display
3981049Sbinkertn@umich.edu        d = display.VectorDisplay()
3991929Sbinkertn@umich.edu        d.name = self.name
4001929Sbinkertn@umich.edu        d.desc = self.desc
4011929Sbinkertn@umich.edu        d.value = [ value(self, run, i) for i in xrange(len(self)) ]
4021929Sbinkertn@umich.edu        d.flags = self.flags
4031929Sbinkertn@umich.edu        d.precision = self.precision
4041049Sbinkertn@umich.edu        d.display()
4051049Sbinkertn@umich.edu
4061929Sbinkertn@umich.educlass Formula(Value):
4071929Sbinkertn@umich.edu    def __getattribute__(self, attr):
4081929Sbinkertn@umich.edu        if attr not in ( '__scalar__', '__vector__', '__value__', '__len__' ):
4091929Sbinkertn@umich.edu            return super(Formula, self).__getattribute__(attr)
4101049Sbinkertn@umich.edu
4111929Sbinkertn@umich.edu        formula = re.sub(':', '__', self.formula)
4121929Sbinkertn@umich.edu        value = eval(formula, self.source.stattop)
4131929Sbinkertn@umich.edu        return getattr(value, attr)
4141049Sbinkertn@umich.edu
4151986Sbinkertn@umich.edu    def __str__(self):
4161986Sbinkertn@umich.edu        return self.name
4171986Sbinkertn@umich.edu
4181929Sbinkertn@umich.educlass SimpleDist(Statistic):
4191049Sbinkertn@umich.edu    def __init__(self, sums, squares, samples):
4201049Sbinkertn@umich.edu        self.sums = sums
4211049Sbinkertn@umich.edu        self.squares = squares
4221049Sbinkertn@umich.edu        self.samples = samples
4231049Sbinkertn@umich.edu
4241049Sbinkertn@umich.edu    def display(self, name, desc, flags, precision):
4251049Sbinkertn@umich.edu        import display
4261049Sbinkertn@umich.edu        p = display.Print()
4271049Sbinkertn@umich.edu        p.flags = flags
4281049Sbinkertn@umich.edu        p.precision = precision
4291049Sbinkertn@umich.edu
4301049Sbinkertn@umich.edu        if self.samples > 0:
4311049Sbinkertn@umich.edu            p.name = name + ".mean"
4321049Sbinkertn@umich.edu            p.value = self.sums / self.samples
4331049Sbinkertn@umich.edu            p.display()
4341049Sbinkertn@umich.edu
4351049Sbinkertn@umich.edu            p.name = name + ".stdev"
4361049Sbinkertn@umich.edu            if self.samples > 1:
4371049Sbinkertn@umich.edu                var = (self.samples * self.squares - self.sums ** 2) \
4381049Sbinkertn@umich.edu                      / (self.samples * (self.samples - 1))
4391049Sbinkertn@umich.edu                if var >= 0:
4401049Sbinkertn@umich.edu                    p.value = math.sqrt(var)
4411049Sbinkertn@umich.edu                else:
4421049Sbinkertn@umich.edu                    p.value = 'NaN'
4431049Sbinkertn@umich.edu            else:
4441049Sbinkertn@umich.edu                p.value = 0.0
4451049Sbinkertn@umich.edu            p.display()
4461049Sbinkertn@umich.edu
4471049Sbinkertn@umich.edu        p.name = name + ".samples"
4481049Sbinkertn@umich.edu        p.value = self.samples
4491049Sbinkertn@umich.edu        p.display()
4501049Sbinkertn@umich.edu
4511049Sbinkertn@umich.edu    def comparable(self, other):
4521049Sbinkertn@umich.edu        return True
4531049Sbinkertn@umich.edu
4541049Sbinkertn@umich.edu    def __eq__(self, other):
4551049Sbinkertn@umich.edu        return self.sums == other.sums and self.squares == other.squares and \
4561049Sbinkertn@umich.edu               self.samples == other.samples
4571049Sbinkertn@umich.edu
4581049Sbinkertn@umich.edu    def __isub__(self, other):
4591049Sbinkertn@umich.edu        self.sums -= other.sums
4601049Sbinkertn@umich.edu        self.squares -= other.squares
4611049Sbinkertn@umich.edu        self.samples -= other.samples
4621049Sbinkertn@umich.edu        return self
4631049Sbinkertn@umich.edu
4641049Sbinkertn@umich.edu    def __iadd__(self, other):
4651049Sbinkertn@umich.edu        self.sums += other.sums
4661049Sbinkertn@umich.edu        self.squares += other.squares
4671049Sbinkertn@umich.edu        self.samples += other.samples
4681049Sbinkertn@umich.edu        return self
4691049Sbinkertn@umich.edu
4701049Sbinkertn@umich.edu    def __itruediv__(self, other):
4711049Sbinkertn@umich.edu        if not other:
4721049Sbinkertn@umich.edu            return self
4731049Sbinkertn@umich.edu        self.sums /= other
4741049Sbinkertn@umich.edu        self.squares /= other
4751049Sbinkertn@umich.edu        self.samples /= other
4761049Sbinkertn@umich.edu        return self
4771049Sbinkertn@umich.edu
4781049Sbinkertn@umich.educlass FullDist(SimpleDist):
4791049Sbinkertn@umich.edu    def __init__(self, sums, squares, samples, minval, maxval,
4801049Sbinkertn@umich.edu                 under, vec, over, min, max, bsize, size):
4811049Sbinkertn@umich.edu        self.sums = sums
4821049Sbinkertn@umich.edu        self.squares = squares
4831049Sbinkertn@umich.edu        self.samples = samples
4841049Sbinkertn@umich.edu        self.minval = minval
4851049Sbinkertn@umich.edu        self.maxval = maxval
4861049Sbinkertn@umich.edu        self.under = under
4871049Sbinkertn@umich.edu        self.vec = vec
4881049Sbinkertn@umich.edu        self.over = over
4891049Sbinkertn@umich.edu        self.min = min
4901049Sbinkertn@umich.edu        self.max = max
4911049Sbinkertn@umich.edu        self.bsize = bsize
4921049Sbinkertn@umich.edu        self.size = size
4931049Sbinkertn@umich.edu
4941049Sbinkertn@umich.edu    def display(self, name, desc, flags, precision):
4951049Sbinkertn@umich.edu        import display
4961049Sbinkertn@umich.edu        p = display.Print()
4971049Sbinkertn@umich.edu        p.flags = flags
4981049Sbinkertn@umich.edu        p.precision = precision
4991049Sbinkertn@umich.edu
5001049Sbinkertn@umich.edu        p.name = name + '.min_val'
5011049Sbinkertn@umich.edu        p.value = self.minval
5021049Sbinkertn@umich.edu        p.display()
5031049Sbinkertn@umich.edu
5041049Sbinkertn@umich.edu        p.name = name + '.max_val'
5051049Sbinkertn@umich.edu        p.value = self.maxval
5061049Sbinkertn@umich.edu        p.display()
5071049Sbinkertn@umich.edu
5081049Sbinkertn@umich.edu        p.name = name + '.underflow'
5091049Sbinkertn@umich.edu        p.value = self.under
5101049Sbinkertn@umich.edu        p.display()
5111049Sbinkertn@umich.edu
5121049Sbinkertn@umich.edu        i = self.min
5131049Sbinkertn@umich.edu        for val in self.vec[:-1]:
5141049Sbinkertn@umich.edu            p.name = name + '[%d:%d]' % (i, i + self.bsize - 1)
5151049Sbinkertn@umich.edu            p.value = val
5161049Sbinkertn@umich.edu            p.display()
5171049Sbinkertn@umich.edu            i += self.bsize
5181049Sbinkertn@umich.edu
5191049Sbinkertn@umich.edu        p.name = name + '[%d:%d]' % (i, self.max)
5201049Sbinkertn@umich.edu        p.value = self.vec[-1]
5211049Sbinkertn@umich.edu        p.display()
5221049Sbinkertn@umich.edu
5231049Sbinkertn@umich.edu
5241049Sbinkertn@umich.edu        p.name = name + '.overflow'
5251049Sbinkertn@umich.edu        p.value = self.over
5261049Sbinkertn@umich.edu        p.display()
5271049Sbinkertn@umich.edu
5281049Sbinkertn@umich.edu        SimpleDist.display(self, name, desc, flags, precision)
5291049Sbinkertn@umich.edu
5301049Sbinkertn@umich.edu    def comparable(self, other):
5311049Sbinkertn@umich.edu        return self.min == other.min and self.max == other.max and \
5321049Sbinkertn@umich.edu               self.bsize == other.bsize and self.size == other.size
5331049Sbinkertn@umich.edu
5341049Sbinkertn@umich.edu    def __eq__(self, other):
5351049Sbinkertn@umich.edu        return self.sums == other.sums and self.squares == other.squares and \
5361049Sbinkertn@umich.edu               self.samples == other.samples
5371049Sbinkertn@umich.edu
5381049Sbinkertn@umich.edu    def __isub__(self, other):
5391049Sbinkertn@umich.edu        self.sums -= other.sums
5401049Sbinkertn@umich.edu        self.squares -= other.squares
5411049Sbinkertn@umich.edu        self.samples -= other.samples
5421049Sbinkertn@umich.edu
5431049Sbinkertn@umich.edu        if other.samples:
5441049Sbinkertn@umich.edu            self.minval = min(self.minval, other.minval)
5451049Sbinkertn@umich.edu            self.maxval = max(self.maxval, other.maxval)
5461049Sbinkertn@umich.edu            self.under -= under
5471049Sbinkertn@umich.edu            self.vec = map(lambda x,y: x - y, self.vec, other.vec)
5481049Sbinkertn@umich.edu            self.over -= over
5491049Sbinkertn@umich.edu        return self
5501049Sbinkertn@umich.edu
5511049Sbinkertn@umich.edu    def __iadd__(self, other):
5521049Sbinkertn@umich.edu        if not self.samples and other.samples:
5531049Sbinkertn@umich.edu            self = other
5541049Sbinkertn@umich.edu            return self
5551049Sbinkertn@umich.edu
5561049Sbinkertn@umich.edu        self.sums += other.sums
5571049Sbinkertn@umich.edu        self.squares += other.squares
5581049Sbinkertn@umich.edu        self.samples += other.samples
5591049Sbinkertn@umich.edu
5601049Sbinkertn@umich.edu        if other.samples:
5611049Sbinkertn@umich.edu            self.minval = min(self.minval, other.minval)
5621049Sbinkertn@umich.edu            self.maxval = max(self.maxval, other.maxval)
5631049Sbinkertn@umich.edu            self.under += other.under
5641049Sbinkertn@umich.edu            self.vec = map(lambda x,y: x + y, self.vec, other.vec)
5651049Sbinkertn@umich.edu            self.over += other.over
5661049Sbinkertn@umich.edu        return self
5671049Sbinkertn@umich.edu
5681049Sbinkertn@umich.edu    def __itruediv__(self, other):
5691049Sbinkertn@umich.edu        if not other:
5701049Sbinkertn@umich.edu            return self
5711049Sbinkertn@umich.edu        self.sums /= other
5721049Sbinkertn@umich.edu        self.squares /= other
5731049Sbinkertn@umich.edu        self.samples /= other
5741049Sbinkertn@umich.edu
5751049Sbinkertn@umich.edu        if self.samples:
5761049Sbinkertn@umich.edu            self.under /= other
5771049Sbinkertn@umich.edu            for i in xrange(len(self.vec)):
5781049Sbinkertn@umich.edu                self.vec[i] /= other
5791049Sbinkertn@umich.edu            self.over /= other
5801049Sbinkertn@umich.edu        return self
5811049Sbinkertn@umich.edu
5821049Sbinkertn@umich.educlass Dist(Statistic):
5831049Sbinkertn@umich.edu    def display(self):
5841049Sbinkertn@umich.edu        import display
5851049Sbinkertn@umich.edu        if not display.all and not (self.flags & flags.printable):
5861049Sbinkertn@umich.edu            return
5871049Sbinkertn@umich.edu
5881049Sbinkertn@umich.edu        self.dist.display(self.name, self.desc, self.flags, self.precision)
5891049Sbinkertn@umich.edu
5901049Sbinkertn@umich.edu    def comparable(self, other):
5911049Sbinkertn@umich.edu        return self.name == other.name and \
5921049Sbinkertn@umich.edu               self.dist.compareable(other.dist)
5931049Sbinkertn@umich.edu
5941049Sbinkertn@umich.edu    def __eq__(self, other):
5951049Sbinkertn@umich.edu        return self.dist == other.dist
5961049Sbinkertn@umich.edu
5971049Sbinkertn@umich.edu    def __isub__(self, other):
5981049Sbinkertn@umich.edu        self.dist -= other.dist
5991049Sbinkertn@umich.edu        return self
6001049Sbinkertn@umich.edu
6011049Sbinkertn@umich.edu    def __iadd__(self, other):
6021049Sbinkertn@umich.edu        self.dist += other.dist
6031049Sbinkertn@umich.edu        return self
6041049Sbinkertn@umich.edu
6051049Sbinkertn@umich.edu    def __itruediv__(self, other):
6061049Sbinkertn@umich.edu        if not other:
6071049Sbinkertn@umich.edu            return self
6081049Sbinkertn@umich.edu        self.dist /= other
6091049Sbinkertn@umich.edu        return self
6101049Sbinkertn@umich.edu
6111049Sbinkertn@umich.educlass VectorDist(Statistic):
6121049Sbinkertn@umich.edu    def display(self):
6131049Sbinkertn@umich.edu        import display
6141049Sbinkertn@umich.edu        if not display.all and not (self.flags & flags.printable):
6151049Sbinkertn@umich.edu            return
6161049Sbinkertn@umich.edu
6171049Sbinkertn@umich.edu        if isinstance(self.dist, SimpleDist):
6181049Sbinkertn@umich.edu            return
6191049Sbinkertn@umich.edu
6201049Sbinkertn@umich.edu        for dist,sn,sd,i in map(None, self.dist, self.subnames, self.subdescs,
6211049Sbinkertn@umich.edu                                range(len(self.dist))):
6221049Sbinkertn@umich.edu            if len(sn) > 0:
6231049Sbinkertn@umich.edu                name = '%s.%s' % (self.name, sn)
6241049Sbinkertn@umich.edu            else:
6251049Sbinkertn@umich.edu                name = '%s[%d]' % (self.name, i)
6261049Sbinkertn@umich.edu
6271049Sbinkertn@umich.edu            if len(sd) > 0:
6281049Sbinkertn@umich.edu                desc = sd
6291049Sbinkertn@umich.edu            else:
6301049Sbinkertn@umich.edu                desc = self.desc
6311049Sbinkertn@umich.edu
6321049Sbinkertn@umich.edu            dist.display(name, desc, self.flags, self.precision)
6331049Sbinkertn@umich.edu
6341049Sbinkertn@umich.edu        if (self.flags & flags.total) or 1:
6351049Sbinkertn@umich.edu            if isinstance(self.dist[0], SimpleDist):
6361049Sbinkertn@umich.edu                disttotal = SimpleDist( \
6371049Sbinkertn@umich.edu                    reduce(sums, [d.sums for d in self.dist]),
6381049Sbinkertn@umich.edu                    reduce(sums, [d.squares for d in self.dist]),
6391049Sbinkertn@umich.edu                    reduce(sums, [d.samples for d in self.dist]))
6401049Sbinkertn@umich.edu            else:
6411049Sbinkertn@umich.edu                disttotal = FullDist( \
6421049Sbinkertn@umich.edu                    reduce(sums, [d.sums for d in self.dist]),
6431049Sbinkertn@umich.edu                    reduce(sums, [d.squares for d in self.dist]),
6441049Sbinkertn@umich.edu                    reduce(sums, [d.samples for d in self.dist]),
6451049Sbinkertn@umich.edu                    min([d.minval for d in self.dist]),
6461049Sbinkertn@umich.edu                    max([d.maxval for d in self.dist]),
6471049Sbinkertn@umich.edu                    reduce(sums, [d.under for d in self.dist]),
6481049Sbinkertn@umich.edu                    reduce(sums, [d.vec for d in self.dist]),
6491049Sbinkertn@umich.edu                    reduce(sums, [d.over for d in self.dist]),
6501049Sbinkertn@umich.edu                    dist[0].min,
6511049Sbinkertn@umich.edu                    dist[0].max,
6521049Sbinkertn@umich.edu                    dist[0].bsize,
6531049Sbinkertn@umich.edu                    dist[0].size)
6541049Sbinkertn@umich.edu
6551049Sbinkertn@umich.edu            name = '%s.total' % (self.name)
6561049Sbinkertn@umich.edu            desc = self.desc
6571049Sbinkertn@umich.edu            disttotal.display(name, desc, self.flags, self.precision)
6581049Sbinkertn@umich.edu
6591049Sbinkertn@umich.edu    def comparable(self, other):
6601049Sbinkertn@umich.edu        return self.name == other.name and \
6611049Sbinkertn@umich.edu               alltrue(map(lambda x, y : x.comparable(y),
6621049Sbinkertn@umich.edu                           self.dist,
6631049Sbinkertn@umich.edu                           other.dist))
6641049Sbinkertn@umich.edu
6651049Sbinkertn@umich.edu    def __eq__(self, other):
6661049Sbinkertn@umich.edu        return alltrue(map(lambda x, y : x == y, self.dist, other.dist))
6671049Sbinkertn@umich.edu
6681049Sbinkertn@umich.edu    def __isub__(self, other):
6691547Sbinkertn@umich.edu        if isinstance(self.dist, (list, tuple)) and \
6701547Sbinkertn@umich.edu               isinstance(other.dist, (list, tuple)):
6711049Sbinkertn@umich.edu            for sd,od in zip(self.dist, other.dist):
6721049Sbinkertn@umich.edu                sd -= od
6731049Sbinkertn@umich.edu        else:
6741049Sbinkertn@umich.edu            self.dist -= other.dist
6751049Sbinkertn@umich.edu        return self
6761049Sbinkertn@umich.edu
6771049Sbinkertn@umich.edu    def __iadd__(self, other):
6781547Sbinkertn@umich.edu        if isinstance(self.dist, (list, tuple)) and \
6791547Sbinkertn@umich.edu               isinstance(other.dist, (list, tuple)):
6801049Sbinkertn@umich.edu            for sd,od in zip(self.dist, other.dist):
6811049Sbinkertn@umich.edu                sd += od
6821049Sbinkertn@umich.edu        else:
6831049Sbinkertn@umich.edu            self.dist += other.dist
6841049Sbinkertn@umich.edu        return self
6851049Sbinkertn@umich.edu
6861049Sbinkertn@umich.edu    def __itruediv__(self, other):
6871049Sbinkertn@umich.edu        if not other:
6881049Sbinkertn@umich.edu            return self
6891547Sbinkertn@umich.edu        if isinstance(self.dist, (list, tuple)):
6901049Sbinkertn@umich.edu            for dist in self.dist:
6911049Sbinkertn@umich.edu                dist /= other
6921049Sbinkertn@umich.edu        else:
6931049Sbinkertn@umich.edu            self.dist /= other
6941049Sbinkertn@umich.edu        return self
6951049Sbinkertn@umich.edu
6961049Sbinkertn@umich.educlass Vector2d(Statistic):
6971049Sbinkertn@umich.edu    def display(self):
6981049Sbinkertn@umich.edu        import display
6991049Sbinkertn@umich.edu        if not display.all and not (self.flags & flags.printable):
7001049Sbinkertn@umich.edu            return
7011049Sbinkertn@umich.edu
7021049Sbinkertn@umich.edu        d = display.VectorDisplay()
7031049Sbinkertn@umich.edu        d.__dict__.update(self.__dict__)
7041049Sbinkertn@umich.edu
7051049Sbinkertn@umich.edu        if self.__dict__.has_key('ysubnames'):
7061049Sbinkertn@umich.edu            ysubnames = list(self.ysubnames)
7071049Sbinkertn@umich.edu            slack = self.x - len(ysubnames)
7081049Sbinkertn@umich.edu            if slack > 0:
7091049Sbinkertn@umich.edu                ysubnames.extend(['']*slack)
7101049Sbinkertn@umich.edu        else:
7111049Sbinkertn@umich.edu            ysubnames = range(self.x)
7121049Sbinkertn@umich.edu
7131049Sbinkertn@umich.edu        for x,sname in enumerate(ysubnames):
7141049Sbinkertn@umich.edu            o = x * self.y
7151049Sbinkertn@umich.edu            d.value = self.value[o:o+self.y]
7161049Sbinkertn@umich.edu            d.name = '%s[%s]' % (self.name, sname)
7171049Sbinkertn@umich.edu            d.display()
7181049Sbinkertn@umich.edu
7191049Sbinkertn@umich.edu        if self.flags & flags.total:
7201049Sbinkertn@umich.edu            d.value = []
7211049Sbinkertn@umich.edu            for y in range(self.y):
7221049Sbinkertn@umich.edu                xtot = 0.0
7231049Sbinkertn@umich.edu                for x in range(self.x):
7241049Sbinkertn@umich.edu                    xtot += self.value[y + x * self.x]
7251049Sbinkertn@umich.edu                d.value.append(xtot)
7261049Sbinkertn@umich.edu
7271049Sbinkertn@umich.edu            d.name = self.name + '.total'
7281049Sbinkertn@umich.edu            d.display()
7291049Sbinkertn@umich.edu
7301049Sbinkertn@umich.edu    def comparable(self, other):
7311049Sbinkertn@umich.edu        return self.name == other.name and self.x == other.x and \
7321049Sbinkertn@umich.edu               self.y == other.y
7331049Sbinkertn@umich.edu
7341049Sbinkertn@umich.edu    def __eq__(self, other):
7351049Sbinkertn@umich.edu        return True
7361049Sbinkertn@umich.edu
7371049Sbinkertn@umich.edu    def __isub__(self, other):
7381049Sbinkertn@umich.edu        return self
7391049Sbinkertn@umich.edu
7401049Sbinkertn@umich.edu    def __iadd__(self, other):
7411049Sbinkertn@umich.edu        return self
7421049Sbinkertn@umich.edu
7431049Sbinkertn@umich.edu    def __itruediv__(self, other):
7441049Sbinkertn@umich.edu        if not other:
7451049Sbinkertn@umich.edu            return self
7461049Sbinkertn@umich.edu        return self
7471049Sbinkertn@umich.edu
7481929Sbinkertn@umich.edudef NewStat(source, data):
7491049Sbinkertn@umich.edu    stat = None
7501049Sbinkertn@umich.edu    if data.type == 'SCALAR':
7511929Sbinkertn@umich.edu        stat = ScalarStat()
7521049Sbinkertn@umich.edu    elif data.type == 'VECTOR':
7531929Sbinkertn@umich.edu        stat = VectorStat()
7541049Sbinkertn@umich.edu    elif data.type == 'DIST':
7551929Sbinkertn@umich.edu        stat = Dist()
7561049Sbinkertn@umich.edu    elif data.type == 'VECTORDIST':
7571929Sbinkertn@umich.edu        stat = VectorDist()
7581049Sbinkertn@umich.edu    elif data.type == 'VECTOR2D':
7591929Sbinkertn@umich.edu        stat = Vector2d()
7601049Sbinkertn@umich.edu    elif data.type == 'FORMULA':
7611929Sbinkertn@umich.edu        stat = Formula()
7621929Sbinkertn@umich.edu
7631929Sbinkertn@umich.edu    stat.__dict__['source'] = source
7641929Sbinkertn@umich.edu    stat.__dict__['ticks'] = None
7651929Sbinkertn@umich.edu    stat.__dict__.update(data.__dict__)
7661049Sbinkertn@umich.edu
7671049Sbinkertn@umich.edu    return stat
7681049Sbinkertn@umich.edu
769