Added stddev/gmean/gstddev to summary.py
This commit is contained in:
+27
-29
@@ -31,7 +31,7 @@ TYPE = 'tTrRdD'
|
|||||||
# integer fields
|
# integer fields
|
||||||
class IntField(co.namedtuple('IntField', 'x')):
|
class IntField(co.namedtuple('IntField', 'x')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
def __new__(cls, x):
|
def __new__(cls, x=0):
|
||||||
if isinstance(x, IntField):
|
if isinstance(x, IntField):
|
||||||
return x
|
return x
|
||||||
if isinstance(x, str):
|
if isinstance(x, str):
|
||||||
@@ -40,13 +40,22 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
# also accept +-∞ and +-inf
|
# also accept +-∞ and +-inf
|
||||||
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('inf')
|
x = m.inf
|
||||||
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('-inf')
|
x = -m.inf
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
assert isinstance(x, int) or m.isinf(x), x
|
||||||
return super().__new__(cls, x)
|
return super().__new__(cls, x)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.x == m.inf:
|
||||||
|
return '∞'
|
||||||
|
elif self.x == -m.inf:
|
||||||
|
return '-∞'
|
||||||
|
else:
|
||||||
|
return str(self.x)
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
assert not m.isinf(self.x)
|
assert not m.isinf(self.x)
|
||||||
return self.x
|
return self.x
|
||||||
@@ -54,14 +63,6 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __float__(self):
|
def __float__(self):
|
||||||
return float(self.x)
|
return float(self.x)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.x == float('inf'):
|
|
||||||
return '∞'
|
|
||||||
elif self.x == float('-inf'):
|
|
||||||
return '-∞'
|
|
||||||
else:
|
|
||||||
return str(self.x)
|
|
||||||
|
|
||||||
none = '%7s' % '-'
|
none = '%7s' % '-'
|
||||||
def table(self):
|
def table(self):
|
||||||
return '%7s' % (self,)
|
return '%7s' % (self,)
|
||||||
@@ -73,9 +74,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
new = self.x if self else 0
|
new = self.x if self else 0
|
||||||
old = other.x if other else 0
|
old = other.x if other else 0
|
||||||
diff = new - old
|
diff = new - old
|
||||||
if diff == float('+inf'):
|
if diff == +m.inf:
|
||||||
return '%7s' % '+∞'
|
return '%7s' % '+∞'
|
||||||
elif diff == float('-inf'):
|
elif diff == -m.inf:
|
||||||
return '%7s' % '-∞'
|
return '%7s' % '-∞'
|
||||||
else:
|
else:
|
||||||
return '%+7d' % diff
|
return '%+7d' % diff
|
||||||
@@ -86,9 +87,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
if m.isinf(new) and m.isinf(old):
|
if m.isinf(new) and m.isinf(old):
|
||||||
return 0.0
|
return 0.0
|
||||||
elif m.isinf(new):
|
elif m.isinf(new):
|
||||||
return float('+inf')
|
return +m.inf
|
||||||
elif m.isinf(old):
|
elif m.isinf(old):
|
||||||
return float('-inf')
|
return -m.inf
|
||||||
elif not old and not new:
|
elif not old and not new:
|
||||||
return 0.0
|
return 0.0
|
||||||
elif not old:
|
elif not old:
|
||||||
@@ -99,6 +100,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return IntField(self.x + other.x)
|
return IntField(self.x + other.x)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return IntField(self.x - other.x)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
return IntField(self.x * other.x)
|
return IntField(self.x * other.x)
|
||||||
|
|
||||||
@@ -114,12 +118,6 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return not self.__lt__(other)
|
return not self.__lt__(other)
|
||||||
|
|
||||||
def __truediv__(self, n):
|
|
||||||
if m.isinf(self.x):
|
|
||||||
return self
|
|
||||||
else:
|
|
||||||
return IntField(round(self.x / n))
|
|
||||||
|
|
||||||
# code size results
|
# code size results
|
||||||
class CodeResult(co.namedtuple('CodeResult', 'file,function,code_size')):
|
class CodeResult(co.namedtuple('CodeResult', 'file,function,code_size')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
@@ -285,8 +283,8 @@ def table(results, diff_results=None, *,
|
|||||||
r.code_size.diff_table()
|
r.code_size.diff_table()
|
||||||
if r else IntField.diff_none,
|
if r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))))
|
else '%+.1f%%' % (100*ratio))))
|
||||||
else:
|
else:
|
||||||
print(' %s %s %s%s' % (
|
print(' %s %s %s%s' % (
|
||||||
@@ -299,8 +297,8 @@ def table(results, diff_results=None, *,
|
|||||||
diff_r.code_size if diff_r else None)
|
diff_r.code_size if diff_r else None)
|
||||||
if r or diff_r else IntField.diff_none,
|
if r or diff_r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))
|
else '%+.1f%%' % (100*ratio))
|
||||||
if ratio else ''))
|
if ratio else ''))
|
||||||
|
|
||||||
@@ -324,8 +322,8 @@ def table(results, diff_results=None, *,
|
|||||||
r.code_size.diff_table()
|
r.code_size.diff_table()
|
||||||
if r else IntField.diff_none,
|
if r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))))
|
else '%+.1f%%' % (100*ratio))))
|
||||||
else:
|
else:
|
||||||
print(' %s %s %s%s' % (
|
print(' %s %s %s%s' % (
|
||||||
@@ -338,8 +336,8 @@ def table(results, diff_results=None, *,
|
|||||||
diff_r.code_size if diff_r else None)
|
diff_r.code_size if diff_r else None)
|
||||||
if r or diff_r else IntField.diff_none,
|
if r or diff_r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))
|
else '%+.1f%%' % (100*ratio))
|
||||||
if ratio else ''))
|
if ratio else ''))
|
||||||
|
|
||||||
|
|||||||
+38
-37
@@ -32,7 +32,7 @@ GCOV_TOOL = ['gcov']
|
|||||||
# integer fields
|
# integer fields
|
||||||
class IntField(co.namedtuple('IntField', 'x')):
|
class IntField(co.namedtuple('IntField', 'x')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
def __new__(cls, x):
|
def __new__(cls, x=0):
|
||||||
if isinstance(x, IntField):
|
if isinstance(x, IntField):
|
||||||
return x
|
return x
|
||||||
if isinstance(x, str):
|
if isinstance(x, str):
|
||||||
@@ -41,13 +41,22 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
# also accept +-∞ and +-inf
|
# also accept +-∞ and +-inf
|
||||||
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('inf')
|
x = m.inf
|
||||||
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('-inf')
|
x = -m.inf
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
assert isinstance(x, int) or m.isinf(x), x
|
||||||
return super().__new__(cls, x)
|
return super().__new__(cls, x)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.x == m.inf:
|
||||||
|
return '∞'
|
||||||
|
elif self.x == -m.inf:
|
||||||
|
return '-∞'
|
||||||
|
else:
|
||||||
|
return str(self.x)
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
assert not m.isinf(self.x)
|
assert not m.isinf(self.x)
|
||||||
return self.x
|
return self.x
|
||||||
@@ -55,14 +64,6 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __float__(self):
|
def __float__(self):
|
||||||
return float(self.x)
|
return float(self.x)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.x == float('inf'):
|
|
||||||
return '∞'
|
|
||||||
elif self.x == float('-inf'):
|
|
||||||
return '-∞'
|
|
||||||
else:
|
|
||||||
return str(self.x)
|
|
||||||
|
|
||||||
none = '%7s' % '-'
|
none = '%7s' % '-'
|
||||||
def table(self):
|
def table(self):
|
||||||
return '%7s' % (self,)
|
return '%7s' % (self,)
|
||||||
@@ -74,9 +75,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
new = self.x if self else 0
|
new = self.x if self else 0
|
||||||
old = other.x if other else 0
|
old = other.x if other else 0
|
||||||
diff = new - old
|
diff = new - old
|
||||||
if diff == float('+inf'):
|
if diff == +m.inf:
|
||||||
return '%7s' % '+∞'
|
return '%7s' % '+∞'
|
||||||
elif diff == float('-inf'):
|
elif diff == -m.inf:
|
||||||
return '%7s' % '-∞'
|
return '%7s' % '-∞'
|
||||||
else:
|
else:
|
||||||
return '%+7d' % diff
|
return '%+7d' % diff
|
||||||
@@ -87,9 +88,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
if m.isinf(new) and m.isinf(old):
|
if m.isinf(new) and m.isinf(old):
|
||||||
return 0.0
|
return 0.0
|
||||||
elif m.isinf(new):
|
elif m.isinf(new):
|
||||||
return float('+inf')
|
return +m.inf
|
||||||
elif m.isinf(old):
|
elif m.isinf(old):
|
||||||
return float('-inf')
|
return -m.inf
|
||||||
elif not old and not new:
|
elif not old and not new:
|
||||||
return 0.0
|
return 0.0
|
||||||
elif not old:
|
elif not old:
|
||||||
@@ -100,6 +101,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return IntField(self.x + other.x)
|
return IntField(self.x + other.x)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return IntField(self.x - other.x)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
return IntField(self.x * other.x)
|
return IntField(self.x * other.x)
|
||||||
|
|
||||||
@@ -115,16 +119,10 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return not self.__lt__(other)
|
return not self.__lt__(other)
|
||||||
|
|
||||||
def __truediv__(self, n):
|
|
||||||
if m.isinf(self.x):
|
|
||||||
return self
|
|
||||||
else:
|
|
||||||
return IntField(round(self.x / n))
|
|
||||||
|
|
||||||
# fractional fields, a/b
|
# fractional fields, a/b
|
||||||
class FracField(co.namedtuple('FracField', 'a,b')):
|
class FracField(co.namedtuple('FracField', 'a,b')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
def __new__(cls, a, b=None):
|
def __new__(cls, a=0, b=None):
|
||||||
if isinstance(a, FracField) and b is None:
|
if isinstance(a, FracField) and b is None:
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str) and b is None:
|
if isinstance(a, str) and b is None:
|
||||||
@@ -136,6 +134,9 @@ class FracField(co.namedtuple('FracField', 'a,b')):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '%s/%s' % (self.a, self.b)
|
return '%s/%s' % (self.a, self.b)
|
||||||
|
|
||||||
|
def __float__(self):
|
||||||
|
return float(self.a)
|
||||||
|
|
||||||
none = '%11s %7s' % ('-', '-')
|
none = '%11s %7s' % ('-', '-')
|
||||||
def table(self):
|
def table(self):
|
||||||
if not self.b.x:
|
if not self.b.x:
|
||||||
@@ -144,8 +145,8 @@ class FracField(co.namedtuple('FracField', 'a,b')):
|
|||||||
t = self.a.x/self.b.x
|
t = self.a.x/self.b.x
|
||||||
return '%11s %7s' % (
|
return '%11s %7s' % (
|
||||||
self,
|
self,
|
||||||
'∞%' if t == float('+inf')
|
'∞%' if t == +m.inf
|
||||||
else '-∞%' if t == float('-inf')
|
else '-∞%' if t == -m.inf
|
||||||
else '%.1f%%' % (100*t))
|
else '%.1f%%' % (100*t))
|
||||||
|
|
||||||
diff_none = '%11s' % '-'
|
diff_none = '%11s' % '-'
|
||||||
@@ -172,12 +173,15 @@ class FracField(co.namedtuple('FracField', 'a,b')):
|
|||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return FracField(self.a + other.a, self.b + other.b)
|
return FracField(self.a + other.a, self.b + other.b)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return FracField(self.a - other.a, self.b - other.b)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
return FracField(self.a * other.a, self.b + other.b)
|
return FracField(self.a * other.a, self.b + other.b)
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
self_r = self.a.x/self.b.x if self.b.x else float('-inf')
|
self_r = self.a.x/self.b.x if self.b.x else -m.inf
|
||||||
other_r = other.a.x/other.b.x if other.b.x else float('-inf')
|
other_r = other.a.x/other.b.x if other.b.x else -m.inf
|
||||||
return self_r < other_r
|
return self_r < other_r
|
||||||
|
|
||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
@@ -189,9 +193,6 @@ class FracField(co.namedtuple('FracField', 'a,b')):
|
|||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return not self.__lt__(other)
|
return not self.__lt__(other)
|
||||||
|
|
||||||
def __truediv__(self, n):
|
|
||||||
return FracField(self.a / n, self.b / n)
|
|
||||||
|
|
||||||
# coverage results
|
# coverage results
|
||||||
class CoverageResult(co.namedtuple('CoverageResult',
|
class CoverageResult(co.namedtuple('CoverageResult',
|
||||||
'file,function,line,'
|
'file,function,line,'
|
||||||
@@ -416,8 +417,8 @@ def table(results, diff_results=None, *,
|
|||||||
r.coverage_branches.diff_table()
|
r.coverage_branches.diff_table()
|
||||||
if r else FracField.diff_none,
|
if r else FracField.diff_none,
|
||||||
' (%s)' % ', '.join(
|
' (%s)' % ', '.join(
|
||||||
'+∞%' if t == float('+inf')
|
'+∞%' if t == +m.inf
|
||||||
else '-∞%' if t == float('-inf')
|
else '-∞%' if t == -m.inf
|
||||||
else '%+.1f%%' % (100*t)
|
else '%+.1f%%' % (100*t)
|
||||||
for t in [line_ratio, branch_ratio])))
|
for t in [line_ratio, branch_ratio])))
|
||||||
else:
|
else:
|
||||||
@@ -439,8 +440,8 @@ def table(results, diff_results=None, *,
|
|||||||
diff_r.coverage_branches if diff_r else None)
|
diff_r.coverage_branches if diff_r else None)
|
||||||
if r or diff_r else FracField.diff_none,
|
if r or diff_r else FracField.diff_none,
|
||||||
' (%s)' % ', '.join(
|
' (%s)' % ', '.join(
|
||||||
'+∞%' if t == float('+inf')
|
'+∞%' if t == +m.inf
|
||||||
else '-∞%' if t == float('-inf')
|
else '-∞%' if t == -m.inf
|
||||||
else '%+.1f%%' % (100*t)
|
else '%+.1f%%' % (100*t)
|
||||||
for t in [line_ratio, branch_ratio]
|
for t in [line_ratio, branch_ratio]
|
||||||
if t)
|
if t)
|
||||||
@@ -473,8 +474,8 @@ def table(results, diff_results=None, *,
|
|||||||
r.coverage_branches.diff_table()
|
r.coverage_branches.diff_table()
|
||||||
if r else FracField.diff_none,
|
if r else FracField.diff_none,
|
||||||
' (%s)' % ', '.join(
|
' (%s)' % ', '.join(
|
||||||
'+∞%' if t == float('+inf')
|
'+∞%' if t == +m.inf
|
||||||
else '-∞%' if t == float('-inf')
|
else '-∞%' if t == -m.inf
|
||||||
else '%+.1f%%' % (100*t)
|
else '%+.1f%%' % (100*t)
|
||||||
for t in [line_ratio, branch_ratio])))
|
for t in [line_ratio, branch_ratio])))
|
||||||
else:
|
else:
|
||||||
@@ -496,8 +497,8 @@ def table(results, diff_results=None, *,
|
|||||||
diff_r.coverage_branches if diff_r else None)
|
diff_r.coverage_branches if diff_r else None)
|
||||||
if r or diff_r else FracField.diff_none,
|
if r or diff_r else FracField.diff_none,
|
||||||
' (%s)' % ', '.join(
|
' (%s)' % ', '.join(
|
||||||
'+∞%' if t == float('+inf')
|
'+∞%' if t == +m.inf
|
||||||
else '-∞%' if t == float('-inf')
|
else '-∞%' if t == -m.inf
|
||||||
else '%+.1f%%' % (100*t)
|
else '%+.1f%%' % (100*t)
|
||||||
for t in [line_ratio, branch_ratio]
|
for t in [line_ratio, branch_ratio]
|
||||||
if t)
|
if t)
|
||||||
|
|||||||
+28
-29
@@ -28,10 +28,11 @@ NM_TOOL = ['nm']
|
|||||||
TYPE = 'dDbB'
|
TYPE = 'dDbB'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# integer fields
|
# integer fields
|
||||||
class IntField(co.namedtuple('IntField', 'x')):
|
class IntField(co.namedtuple('IntField', 'x')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
def __new__(cls, x):
|
def __new__(cls, x=0):
|
||||||
if isinstance(x, IntField):
|
if isinstance(x, IntField):
|
||||||
return x
|
return x
|
||||||
if isinstance(x, str):
|
if isinstance(x, str):
|
||||||
@@ -40,13 +41,22 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
# also accept +-∞ and +-inf
|
# also accept +-∞ and +-inf
|
||||||
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('inf')
|
x = m.inf
|
||||||
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('-inf')
|
x = -m.inf
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
assert isinstance(x, int) or m.isinf(x), x
|
||||||
return super().__new__(cls, x)
|
return super().__new__(cls, x)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.x == m.inf:
|
||||||
|
return '∞'
|
||||||
|
elif self.x == -m.inf:
|
||||||
|
return '-∞'
|
||||||
|
else:
|
||||||
|
return str(self.x)
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
assert not m.isinf(self.x)
|
assert not m.isinf(self.x)
|
||||||
return self.x
|
return self.x
|
||||||
@@ -54,14 +64,6 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __float__(self):
|
def __float__(self):
|
||||||
return float(self.x)
|
return float(self.x)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.x == float('inf'):
|
|
||||||
return '∞'
|
|
||||||
elif self.x == float('-inf'):
|
|
||||||
return '-∞'
|
|
||||||
else:
|
|
||||||
return str(self.x)
|
|
||||||
|
|
||||||
none = '%7s' % '-'
|
none = '%7s' % '-'
|
||||||
def table(self):
|
def table(self):
|
||||||
return '%7s' % (self,)
|
return '%7s' % (self,)
|
||||||
@@ -73,9 +75,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
new = self.x if self else 0
|
new = self.x if self else 0
|
||||||
old = other.x if other else 0
|
old = other.x if other else 0
|
||||||
diff = new - old
|
diff = new - old
|
||||||
if diff == float('+inf'):
|
if diff == +m.inf:
|
||||||
return '%7s' % '+∞'
|
return '%7s' % '+∞'
|
||||||
elif diff == float('-inf'):
|
elif diff == -m.inf:
|
||||||
return '%7s' % '-∞'
|
return '%7s' % '-∞'
|
||||||
else:
|
else:
|
||||||
return '%+7d' % diff
|
return '%+7d' % diff
|
||||||
@@ -86,9 +88,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
if m.isinf(new) and m.isinf(old):
|
if m.isinf(new) and m.isinf(old):
|
||||||
return 0.0
|
return 0.0
|
||||||
elif m.isinf(new):
|
elif m.isinf(new):
|
||||||
return float('+inf')
|
return +m.inf
|
||||||
elif m.isinf(old):
|
elif m.isinf(old):
|
||||||
return float('-inf')
|
return -m.inf
|
||||||
elif not old and not new:
|
elif not old and not new:
|
||||||
return 0.0
|
return 0.0
|
||||||
elif not old:
|
elif not old:
|
||||||
@@ -99,6 +101,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return IntField(self.x + other.x)
|
return IntField(self.x + other.x)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return IntField(self.x - other.x)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
return IntField(self.x * other.x)
|
return IntField(self.x * other.x)
|
||||||
|
|
||||||
@@ -114,12 +119,6 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return not self.__lt__(other)
|
return not self.__lt__(other)
|
||||||
|
|
||||||
def __truediv__(self, n):
|
|
||||||
if m.isinf(self.x):
|
|
||||||
return self
|
|
||||||
else:
|
|
||||||
return IntField(round(self.x / n))
|
|
||||||
|
|
||||||
# data size results
|
# data size results
|
||||||
class DataResult(co.namedtuple('DataResult', 'file,function,data_size')):
|
class DataResult(co.namedtuple('DataResult', 'file,function,data_size')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
@@ -285,8 +284,8 @@ def table(results, diff_results=None, *,
|
|||||||
r.data_size.diff_table()
|
r.data_size.diff_table()
|
||||||
if r else IntField.diff_none,
|
if r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))))
|
else '%+.1f%%' % (100*ratio))))
|
||||||
else:
|
else:
|
||||||
print(' %s %s %s%s' % (
|
print(' %s %s %s%s' % (
|
||||||
@@ -299,8 +298,8 @@ def table(results, diff_results=None, *,
|
|||||||
diff_r.data_size if diff_r else None)
|
diff_r.data_size if diff_r else None)
|
||||||
if r or diff_r else IntField.diff_none,
|
if r or diff_r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))
|
else '%+.1f%%' % (100*ratio))
|
||||||
if ratio else ''))
|
if ratio else ''))
|
||||||
|
|
||||||
@@ -324,8 +323,8 @@ def table(results, diff_results=None, *,
|
|||||||
r.data_size.diff_table()
|
r.data_size.diff_table()
|
||||||
if r else IntField.diff_none,
|
if r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))))
|
else '%+.1f%%' % (100*ratio))))
|
||||||
else:
|
else:
|
||||||
print(' %s %s %s%s' % (
|
print(' %s %s %s%s' % (
|
||||||
@@ -338,8 +337,8 @@ def table(results, diff_results=None, *,
|
|||||||
diff_r.data_size if diff_r else None)
|
diff_r.data_size if diff_r else None)
|
||||||
if r or diff_r else IntField.diff_none,
|
if r or diff_r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))
|
else '%+.1f%%' % (100*ratio))
|
||||||
if ratio else ''))
|
if ratio else ''))
|
||||||
|
|
||||||
|
|||||||
+27
-29
@@ -25,7 +25,7 @@ CI_PATHS = ['*.ci']
|
|||||||
# integer fields
|
# integer fields
|
||||||
class IntField(co.namedtuple('IntField', 'x')):
|
class IntField(co.namedtuple('IntField', 'x')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
def __new__(cls, x):
|
def __new__(cls, x=0):
|
||||||
if isinstance(x, IntField):
|
if isinstance(x, IntField):
|
||||||
return x
|
return x
|
||||||
if isinstance(x, str):
|
if isinstance(x, str):
|
||||||
@@ -34,13 +34,22 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
# also accept +-∞ and +-inf
|
# also accept +-∞ and +-inf
|
||||||
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('inf')
|
x = m.inf
|
||||||
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('-inf')
|
x = -m.inf
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
assert isinstance(x, int) or m.isinf(x), x
|
||||||
return super().__new__(cls, x)
|
return super().__new__(cls, x)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.x == m.inf:
|
||||||
|
return '∞'
|
||||||
|
elif self.x == -m.inf:
|
||||||
|
return '-∞'
|
||||||
|
else:
|
||||||
|
return str(self.x)
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
assert not m.isinf(self.x)
|
assert not m.isinf(self.x)
|
||||||
return self.x
|
return self.x
|
||||||
@@ -48,14 +57,6 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __float__(self):
|
def __float__(self):
|
||||||
return float(self.x)
|
return float(self.x)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.x == float('inf'):
|
|
||||||
return '∞'
|
|
||||||
elif self.x == float('-inf'):
|
|
||||||
return '-∞'
|
|
||||||
else:
|
|
||||||
return str(self.x)
|
|
||||||
|
|
||||||
none = '%7s' % '-'
|
none = '%7s' % '-'
|
||||||
def table(self):
|
def table(self):
|
||||||
return '%7s' % (self,)
|
return '%7s' % (self,)
|
||||||
@@ -67,9 +68,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
new = self.x if self else 0
|
new = self.x if self else 0
|
||||||
old = other.x if other else 0
|
old = other.x if other else 0
|
||||||
diff = new - old
|
diff = new - old
|
||||||
if diff == float('+inf'):
|
if diff == +m.inf:
|
||||||
return '%7s' % '+∞'
|
return '%7s' % '+∞'
|
||||||
elif diff == float('-inf'):
|
elif diff == -m.inf:
|
||||||
return '%7s' % '-∞'
|
return '%7s' % '-∞'
|
||||||
else:
|
else:
|
||||||
return '%+7d' % diff
|
return '%+7d' % diff
|
||||||
@@ -80,9 +81,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
if m.isinf(new) and m.isinf(old):
|
if m.isinf(new) and m.isinf(old):
|
||||||
return 0.0
|
return 0.0
|
||||||
elif m.isinf(new):
|
elif m.isinf(new):
|
||||||
return float('+inf')
|
return +m.inf
|
||||||
elif m.isinf(old):
|
elif m.isinf(old):
|
||||||
return float('-inf')
|
return -m.inf
|
||||||
elif not old and not new:
|
elif not old and not new:
|
||||||
return 0.0
|
return 0.0
|
||||||
elif not old:
|
elif not old:
|
||||||
@@ -93,6 +94,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return IntField(self.x + other.x)
|
return IntField(self.x + other.x)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return IntField(self.x - other.x)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
return IntField(self.x * other.x)
|
return IntField(self.x * other.x)
|
||||||
|
|
||||||
@@ -108,12 +112,6 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return not self.__lt__(other)
|
return not self.__lt__(other)
|
||||||
|
|
||||||
def __truediv__(self, n):
|
|
||||||
if m.isinf(self.x):
|
|
||||||
return self
|
|
||||||
else:
|
|
||||||
return IntField(round(self.x / n))
|
|
||||||
|
|
||||||
# size results
|
# size results
|
||||||
class StackResult(co.namedtuple('StackResult',
|
class StackResult(co.namedtuple('StackResult',
|
||||||
'file,function,stack_frame,stack_limit')):
|
'file,function,stack_frame,stack_limit')):
|
||||||
@@ -394,8 +392,8 @@ def table(results, calls, diff_results=None, *,
|
|||||||
r.stack_limit.diff_table()
|
r.stack_limit.diff_table()
|
||||||
if r else IntField.diff_none,
|
if r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))))
|
else '%+.1f%%' % (100*ratio))))
|
||||||
else:
|
else:
|
||||||
print(' %s %s %s %s %s %s%s' % (
|
print(' %s %s %s %s %s %s%s' % (
|
||||||
@@ -416,8 +414,8 @@ def table(results, calls, diff_results=None, *,
|
|||||||
diff_r.stack_limit if diff_r else None)
|
diff_r.stack_limit if diff_r else None)
|
||||||
if r or diff_r else IntField.diff_none,
|
if r or diff_r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))
|
else '%+.1f%%' % (100*ratio))
|
||||||
if ratio else ''))
|
if ratio else ''))
|
||||||
|
|
||||||
@@ -460,8 +458,8 @@ def table(results, calls, diff_results=None, *,
|
|||||||
r.stack_limit.diff_table()
|
r.stack_limit.diff_table()
|
||||||
if r else IntField.diff_none,
|
if r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))))
|
else '%+.1f%%' % (100*ratio))))
|
||||||
else:
|
else:
|
||||||
print(' %s %s %s %s %s %s%s' % (
|
print(' %s %s %s %s %s %s%s' % (
|
||||||
@@ -482,8 +480,8 @@ def table(results, calls, diff_results=None, *,
|
|||||||
diff_r.stack_limit if diff_r else None)
|
diff_r.stack_limit if diff_r else None)
|
||||||
if r or diff_r else IntField.diff_none,
|
if r or diff_r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))
|
else '%+.1f%%' % (100*ratio))
|
||||||
if ratio else ''))
|
if ratio else ''))
|
||||||
|
|
||||||
|
|||||||
+27
-29
@@ -27,7 +27,7 @@ OBJDUMP_TOOL = ['objdump']
|
|||||||
# integer fields
|
# integer fields
|
||||||
class IntField(co.namedtuple('IntField', 'x')):
|
class IntField(co.namedtuple('IntField', 'x')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
def __new__(cls, x):
|
def __new__(cls, x=0):
|
||||||
if isinstance(x, IntField):
|
if isinstance(x, IntField):
|
||||||
return x
|
return x
|
||||||
if isinstance(x, str):
|
if isinstance(x, str):
|
||||||
@@ -36,13 +36,22 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
# also accept +-∞ and +-inf
|
# also accept +-∞ and +-inf
|
||||||
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('inf')
|
x = m.inf
|
||||||
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('-inf')
|
x = -m.inf
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
assert isinstance(x, int) or m.isinf(x), x
|
||||||
return super().__new__(cls, x)
|
return super().__new__(cls, x)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.x == m.inf:
|
||||||
|
return '∞'
|
||||||
|
elif self.x == -m.inf:
|
||||||
|
return '-∞'
|
||||||
|
else:
|
||||||
|
return str(self.x)
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
assert not m.isinf(self.x)
|
assert not m.isinf(self.x)
|
||||||
return self.x
|
return self.x
|
||||||
@@ -50,14 +59,6 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __float__(self):
|
def __float__(self):
|
||||||
return float(self.x)
|
return float(self.x)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.x == float('inf'):
|
|
||||||
return '∞'
|
|
||||||
elif self.x == float('-inf'):
|
|
||||||
return '-∞'
|
|
||||||
else:
|
|
||||||
return str(self.x)
|
|
||||||
|
|
||||||
none = '%7s' % '-'
|
none = '%7s' % '-'
|
||||||
def table(self):
|
def table(self):
|
||||||
return '%7s' % (self,)
|
return '%7s' % (self,)
|
||||||
@@ -69,9 +70,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
new = self.x if self else 0
|
new = self.x if self else 0
|
||||||
old = other.x if other else 0
|
old = other.x if other else 0
|
||||||
diff = new - old
|
diff = new - old
|
||||||
if diff == float('+inf'):
|
if diff == +m.inf:
|
||||||
return '%7s' % '+∞'
|
return '%7s' % '+∞'
|
||||||
elif diff == float('-inf'):
|
elif diff == -m.inf:
|
||||||
return '%7s' % '-∞'
|
return '%7s' % '-∞'
|
||||||
else:
|
else:
|
||||||
return '%+7d' % diff
|
return '%+7d' % diff
|
||||||
@@ -82,9 +83,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
if m.isinf(new) and m.isinf(old):
|
if m.isinf(new) and m.isinf(old):
|
||||||
return 0.0
|
return 0.0
|
||||||
elif m.isinf(new):
|
elif m.isinf(new):
|
||||||
return float('+inf')
|
return +m.inf
|
||||||
elif m.isinf(old):
|
elif m.isinf(old):
|
||||||
return float('-inf')
|
return -m.inf
|
||||||
elif not old and not new:
|
elif not old and not new:
|
||||||
return 0.0
|
return 0.0
|
||||||
elif not old:
|
elif not old:
|
||||||
@@ -95,6 +96,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return IntField(self.x + other.x)
|
return IntField(self.x + other.x)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return IntField(self.x - other.x)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
return IntField(self.x * other.x)
|
return IntField(self.x * other.x)
|
||||||
|
|
||||||
@@ -110,12 +114,6 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return not self.__lt__(other)
|
return not self.__lt__(other)
|
||||||
|
|
||||||
def __truediv__(self, n):
|
|
||||||
if m.isinf(self.x):
|
|
||||||
return self
|
|
||||||
else:
|
|
||||||
return IntField(round(self.x / n))
|
|
||||||
|
|
||||||
# struct size results
|
# struct size results
|
||||||
class StructResult(co.namedtuple('StructResult', 'file,struct,struct_size')):
|
class StructResult(co.namedtuple('StructResult', 'file,struct,struct_size')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
@@ -328,8 +326,8 @@ def table(results, diff_results=None, *,
|
|||||||
r.struct_size.diff_table()
|
r.struct_size.diff_table()
|
||||||
if r else IntField.diff_none,
|
if r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))))
|
else '%+.1f%%' % (100*ratio))))
|
||||||
else:
|
else:
|
||||||
print(' %s %s %s%s' % (
|
print(' %s %s %s%s' % (
|
||||||
@@ -342,8 +340,8 @@ def table(results, diff_results=None, *,
|
|||||||
diff_r.struct_size if diff_r else None)
|
diff_r.struct_size if diff_r else None)
|
||||||
if r or diff_r else IntField.diff_none,
|
if r or diff_r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))
|
else '%+.1f%%' % (100*ratio))
|
||||||
if ratio else ''))
|
if ratio else ''))
|
||||||
|
|
||||||
@@ -367,8 +365,8 @@ def table(results, diff_results=None, *,
|
|||||||
r.struct_size.diff_table()
|
r.struct_size.diff_table()
|
||||||
if r else IntField.diff_none,
|
if r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))))
|
else '%+.1f%%' % (100*ratio))))
|
||||||
else:
|
else:
|
||||||
print(' %s %s %s%s' % (
|
print(' %s %s %s%s' % (
|
||||||
@@ -381,8 +379,8 @@ def table(results, diff_results=None, *,
|
|||||||
diff_r.struct_size if diff_r else None)
|
diff_r.struct_size if diff_r else None)
|
||||||
if r or diff_r else IntField.diff_none,
|
if r or diff_r else IntField.diff_none,
|
||||||
' (%s)' % (
|
' (%s)' % (
|
||||||
'+∞%' if ratio == float('+inf')
|
'+∞%' if ratio == +m.inf
|
||||||
else '-∞%' if ratio == float('-inf')
|
else '-∞%' if ratio == -m.inf
|
||||||
else '%+.1f%%' % (100*ratio))
|
else '%+.1f%%' % (100*ratio))
|
||||||
if ratio else ''))
|
if ratio else ''))
|
||||||
|
|
||||||
|
|||||||
+119
-77
@@ -25,12 +25,26 @@ import re
|
|||||||
CSV_PATHS = ['*.csv']
|
CSV_PATHS = ['*.csv']
|
||||||
|
|
||||||
# supported merge operations
|
# supported merge operations
|
||||||
|
#
|
||||||
|
# this is a terrible way to express these
|
||||||
|
#
|
||||||
OPS = {
|
OPS = {
|
||||||
'add': lambda xs: sum(xs[1:], start=xs[0]),
|
'sum': lambda xs: sum(xs[1:], start=xs[0]),
|
||||||
'mul': lambda xs: m.prod(xs[1:], start=xs[0]),
|
'prod': lambda xs: m.prod(xs[1:], start=xs[0]),
|
||||||
'min': min,
|
'min': min,
|
||||||
'max': max,
|
'max': max,
|
||||||
'avg': lambda xs: sum(xs[1:], start=xs[0]) / len(xs),
|
'mean': lambda xs: FloatField(sum(float(x) for x in xs) / len(xs)),
|
||||||
|
'stddev': lambda xs: (
|
||||||
|
lambda mean: FloatField(
|
||||||
|
m.sqrt(sum((float(x) - mean)**2 for x in xs) / len(xs)))
|
||||||
|
)(sum(float(x) for x in xs) / len(xs)),
|
||||||
|
'gmean': lambda xs: FloatField(m.prod(float(x) for x in xs)**(1/len(xs))),
|
||||||
|
'gstddev': lambda xs: (
|
||||||
|
lambda gmean: FloatField(
|
||||||
|
m.exp(m.sqrt(sum(m.log(float(x)/gmean)**2 for x in xs) / len(xs)))
|
||||||
|
if gmean else m.inf)
|
||||||
|
)(m.prod(float(x) for x in xs)**(1/len(xs)))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -47,7 +61,7 @@ def openio(path, mode='r'):
|
|||||||
# integer fields
|
# integer fields
|
||||||
class IntField(co.namedtuple('IntField', 'x')):
|
class IntField(co.namedtuple('IntField', 'x')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
def __new__(cls, x):
|
def __new__(cls, x=0):
|
||||||
if isinstance(x, IntField):
|
if isinstance(x, IntField):
|
||||||
return x
|
return x
|
||||||
if isinstance(x, str):
|
if isinstance(x, str):
|
||||||
@@ -56,13 +70,22 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
# also accept +-∞ and +-inf
|
# also accept +-∞ and +-inf
|
||||||
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('inf')
|
x = m.inf
|
||||||
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('-inf')
|
x = -m.inf
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
assert isinstance(x, int) or m.isinf(x), x
|
||||||
return super().__new__(cls, x)
|
return super().__new__(cls, x)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.x == m.inf:
|
||||||
|
return '∞'
|
||||||
|
elif self.x == -m.inf:
|
||||||
|
return '-∞'
|
||||||
|
else:
|
||||||
|
return str(self.x)
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self):
|
||||||
assert not m.isinf(self.x)
|
assert not m.isinf(self.x)
|
||||||
return self.x
|
return self.x
|
||||||
@@ -70,14 +93,6 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __float__(self):
|
def __float__(self):
|
||||||
return float(self.x)
|
return float(self.x)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.x == float('inf'):
|
|
||||||
return '∞'
|
|
||||||
elif self.x == float('-inf'):
|
|
||||||
return '-∞'
|
|
||||||
else:
|
|
||||||
return str(self.x)
|
|
||||||
|
|
||||||
none = '%7s' % '-'
|
none = '%7s' % '-'
|
||||||
def table(self):
|
def table(self):
|
||||||
return '%7s' % (self,)
|
return '%7s' % (self,)
|
||||||
@@ -89,9 +104,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
new = self.x if self else 0
|
new = self.x if self else 0
|
||||||
old = other.x if other else 0
|
old = other.x if other else 0
|
||||||
diff = new - old
|
diff = new - old
|
||||||
if diff == float('+inf'):
|
if diff == +m.inf:
|
||||||
return '%7s' % '+∞'
|
return '%7s' % '+∞'
|
||||||
elif diff == float('-inf'):
|
elif diff == -m.inf:
|
||||||
return '%7s' % '-∞'
|
return '%7s' % '-∞'
|
||||||
else:
|
else:
|
||||||
return '%+7d' % diff
|
return '%+7d' % diff
|
||||||
@@ -102,9 +117,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
if m.isinf(new) and m.isinf(old):
|
if m.isinf(new) and m.isinf(old):
|
||||||
return 0.0
|
return 0.0
|
||||||
elif m.isinf(new):
|
elif m.isinf(new):
|
||||||
return float('+inf')
|
return +m.inf
|
||||||
elif m.isinf(old):
|
elif m.isinf(old):
|
||||||
return float('-inf')
|
return -m.inf
|
||||||
elif not old and not new:
|
elif not old and not new:
|
||||||
return 0.0
|
return 0.0
|
||||||
elif not old:
|
elif not old:
|
||||||
@@ -115,6 +130,9 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return IntField(self.x + other.x)
|
return IntField(self.x + other.x)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return IntField(self.x - other.x)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
return IntField(self.x * other.x)
|
return IntField(self.x * other.x)
|
||||||
|
|
||||||
@@ -130,16 +148,10 @@ class IntField(co.namedtuple('IntField', 'x')):
|
|||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return not self.__lt__(other)
|
return not self.__lt__(other)
|
||||||
|
|
||||||
def __truediv__(self, n):
|
|
||||||
if m.isinf(self.x):
|
|
||||||
return self
|
|
||||||
else:
|
|
||||||
return IntField(round(self.x / n))
|
|
||||||
|
|
||||||
# float fields
|
# float fields
|
||||||
class FloatField(co.namedtuple('FloatField', 'x')):
|
class FloatField(co.namedtuple('FloatField', 'x')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
def __new__(cls, x):
|
def __new__(cls, x=0.0):
|
||||||
if isinstance(x, FloatField):
|
if isinstance(x, FloatField):
|
||||||
return x
|
return x
|
||||||
if isinstance(x, str):
|
if isinstance(x, str):
|
||||||
@@ -148,24 +160,25 @@ class FloatField(co.namedtuple('FloatField', 'x')):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
# also accept +-∞ and +-inf
|
# also accept +-∞ and +-inf
|
||||||
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
if re.match('^\s*\+?\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('inf')
|
x = m.inf
|
||||||
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
elif re.match('^\s*-\s*(?:∞|inf)\s*$', x):
|
||||||
x = float('-inf')
|
x = -m.inf
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
assert isinstance(x, float), x
|
||||||
return super().__new__(cls, x)
|
return super().__new__(cls, x)
|
||||||
|
|
||||||
def __float__(self):
|
|
||||||
return float(self.x)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.x == float('inf'):
|
if self.x == m.inf:
|
||||||
return '∞'
|
return '∞'
|
||||||
elif self.x == float('-inf'):
|
elif self.x == -m.inf:
|
||||||
return '-∞'
|
return '-∞'
|
||||||
else:
|
else:
|
||||||
return '%.1f' % self.x
|
return '%.1f' % self.x
|
||||||
|
|
||||||
|
def __float__(self):
|
||||||
|
return float(self.x)
|
||||||
|
|
||||||
none = IntField.none
|
none = IntField.none
|
||||||
table = IntField.table
|
table = IntField.table
|
||||||
diff_none = IntField.diff_none
|
diff_none = IntField.diff_none
|
||||||
@@ -173,22 +186,17 @@ class FloatField(co.namedtuple('FloatField', 'x')):
|
|||||||
diff_diff = IntField.diff_diff
|
diff_diff = IntField.diff_diff
|
||||||
ratio = IntField.ratio
|
ratio = IntField.ratio
|
||||||
__add__ = IntField.__add__
|
__add__ = IntField.__add__
|
||||||
|
__sub__ = IntField.__sub__
|
||||||
__mul__ = IntField.__mul__
|
__mul__ = IntField.__mul__
|
||||||
__lt__ = IntField.__lt__
|
__lt__ = IntField.__lt__
|
||||||
__gt__ = IntField.__gt__
|
__gt__ = IntField.__gt__
|
||||||
__le__ = IntField.__le__
|
__le__ = IntField.__le__
|
||||||
__ge__ = IntField.__ge__
|
__ge__ = IntField.__ge__
|
||||||
|
|
||||||
def __truediv__(self, n):
|
|
||||||
if m.isinf(self.x):
|
|
||||||
return self
|
|
||||||
else:
|
|
||||||
return FloatField(self.x / n)
|
|
||||||
|
|
||||||
# fractional fields, a/b
|
# fractional fields, a/b
|
||||||
class FracField(co.namedtuple('FracField', 'a,b')):
|
class FracField(co.namedtuple('FracField', 'a,b')):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
def __new__(cls, a, b=None):
|
def __new__(cls, a=0, b=None):
|
||||||
if isinstance(a, FracField) and b is None:
|
if isinstance(a, FracField) and b is None:
|
||||||
return a
|
return a
|
||||||
if isinstance(a, str) and b is None:
|
if isinstance(a, str) and b is None:
|
||||||
@@ -200,6 +208,9 @@ class FracField(co.namedtuple('FracField', 'a,b')):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '%s/%s' % (self.a, self.b)
|
return '%s/%s' % (self.a, self.b)
|
||||||
|
|
||||||
|
def __float__(self):
|
||||||
|
return float(self.a)
|
||||||
|
|
||||||
none = '%11s %7s' % ('-', '-')
|
none = '%11s %7s' % ('-', '-')
|
||||||
def table(self):
|
def table(self):
|
||||||
if not self.b.x:
|
if not self.b.x:
|
||||||
@@ -208,8 +219,8 @@ class FracField(co.namedtuple('FracField', 'a,b')):
|
|||||||
t = self.a.x/self.b.x
|
t = self.a.x/self.b.x
|
||||||
return '%11s %7s' % (
|
return '%11s %7s' % (
|
||||||
self,
|
self,
|
||||||
'∞%' if t == float('+inf')
|
'∞%' if t == +m.inf
|
||||||
else '-∞%' if t == float('-inf')
|
else '-∞%' if t == -m.inf
|
||||||
else '%.1f%%' % (100*t))
|
else '%.1f%%' % (100*t))
|
||||||
|
|
||||||
diff_none = '%11s' % '-'
|
diff_none = '%11s' % '-'
|
||||||
@@ -236,12 +247,15 @@ class FracField(co.namedtuple('FracField', 'a,b')):
|
|||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
return FracField(self.a + other.a, self.b + other.b)
|
return FracField(self.a + other.a, self.b + other.b)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return FracField(self.a - other.a, self.b - other.b)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
return FracField(self.a * other.a, self.b + other.b)
|
return FracField(self.a * other.a, self.b + other.b)
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
self_r = self.a.x/self.b.x if self.b.x else float('-inf')
|
self_r = self.a.x/self.b.x if self.b.x else -m.inf
|
||||||
other_r = other.a.x/other.b.x if other.b.x else float('-inf')
|
other_r = other.a.x/other.b.x if other.b.x else -m.inf
|
||||||
return self_r < other_r
|
return self_r < other_r
|
||||||
|
|
||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
@@ -253,9 +267,6 @@ class FracField(co.namedtuple('FracField', 'a,b')):
|
|||||||
def __ge__(self, other):
|
def __ge__(self, other):
|
||||||
return not self.__lt__(other)
|
return not self.__lt__(other)
|
||||||
|
|
||||||
def __truediv__(self, n):
|
|
||||||
return FracField(self.a / n, self.b / n)
|
|
||||||
|
|
||||||
# available types
|
# available types
|
||||||
TYPES = [IntField, FloatField, FracField]
|
TYPES = [IntField, FloatField, FracField]
|
||||||
|
|
||||||
@@ -314,7 +325,7 @@ def homogenize(results, *,
|
|||||||
if k is not None
|
if k is not None
|
||||||
and k not in fields
|
and k not in fields
|
||||||
and not any(k == old_k for _, old_k in renames))
|
and not any(k == old_k for _, old_k in renames))
|
||||||
by = list(by.keys())
|
by = list(by.keys())
|
||||||
|
|
||||||
# go ahead and clean up none values, these can have a few forms
|
# go ahead and clean up none values, these can have a few forms
|
||||||
results_ = []
|
results_ = []
|
||||||
@@ -357,6 +368,7 @@ def homogenize(results, *,
|
|||||||
def fold(results, *,
|
def fold(results, *,
|
||||||
by=[],
|
by=[],
|
||||||
fields=[],
|
fields=[],
|
||||||
|
types=None,
|
||||||
ops={},
|
ops={},
|
||||||
**_):
|
**_):
|
||||||
folding = co.OrderedDict()
|
folding = co.OrderedDict()
|
||||||
@@ -375,7 +387,7 @@ def fold(results, *,
|
|||||||
for k, vs in r.items():
|
for k, vs in r.items():
|
||||||
if vs:
|
if vs:
|
||||||
# sum fields by default
|
# sum fields by default
|
||||||
op = OPS[ops.get(k, 'add')]
|
op = OPS[ops.get(k, 'sum')]
|
||||||
r_[k] = op(vs)
|
r_[k] = op(vs)
|
||||||
|
|
||||||
# drop any rows without fields and any empty keys
|
# drop any rows without fields and any empty keys
|
||||||
@@ -384,14 +396,24 @@ def fold(results, *,
|
|||||||
{k: v for k, v in zip(by, name) if v},
|
{k: v for k, v in zip(by, name) if v},
|
||||||
**r_))
|
**r_))
|
||||||
|
|
||||||
return folded
|
# what is the type of merged fields?
|
||||||
|
if types is not None:
|
||||||
|
types_ = {}
|
||||||
|
for k in fields:
|
||||||
|
op = OPS[ops.get(k, 'sum')]
|
||||||
|
types_[k] = op([types[k]()]).__class__
|
||||||
|
|
||||||
|
if types is None:
|
||||||
|
return folded
|
||||||
|
else:
|
||||||
|
return types_, folded
|
||||||
|
|
||||||
|
|
||||||
def table(results, diff_results=None, *,
|
def table(results, total, diff_results=None, diff_total=None, *,
|
||||||
by=None,
|
by=[],
|
||||||
fields=None,
|
fields=[],
|
||||||
types=None,
|
types={},
|
||||||
ops=None,
|
ops={},
|
||||||
sort=None,
|
sort=None,
|
||||||
reverse_sort=None,
|
reverse_sort=None,
|
||||||
summary=False,
|
summary=False,
|
||||||
@@ -472,8 +494,8 @@ def table(results, diff_results=None, *,
|
|||||||
if k in r else types[k].diff_none
|
if k in r else types[k].diff_none
|
||||||
for k in fields),
|
for k in fields),
|
||||||
' (%s)' % ', '.join(
|
' (%s)' % ', '.join(
|
||||||
'+∞%' if t == float('+inf')
|
'+∞%' if t == +m.inf
|
||||||
else '-∞%' if t == float('-inf')
|
else '-∞%' if t == -m.inf
|
||||||
else '%+.1f%%' % (100*t)
|
else '%+.1f%%' % (100*t)
|
||||||
for t in ratios)))
|
for t in ratios)))
|
||||||
else:
|
else:
|
||||||
@@ -488,19 +510,17 @@ def table(results, diff_results=None, *,
|
|||||||
if k in r or k in diff_r else types[k].diff_none
|
if k in r or k in diff_r else types[k].diff_none
|
||||||
for k in fields),
|
for k in fields),
|
||||||
' (%s)' % ', '.join(
|
' (%s)' % ', '.join(
|
||||||
'+∞%' if t == float('+inf')
|
'+∞%' if t == +m.inf
|
||||||
else '-∞%' if t == float('-inf')
|
else '-∞%' if t == -m.inf
|
||||||
else '%+.1f%%' % (100*t)
|
else '%+.1f%%' % (100*t)
|
||||||
for t in ratios
|
for t in ratios
|
||||||
if t)
|
if t)
|
||||||
if any(ratios) else ''))
|
if any(ratios) else ''))
|
||||||
|
|
||||||
# print total
|
# print total
|
||||||
total = fold(results, by=[], fields=fields, ops=ops)
|
r = total
|
||||||
r = total[0] if total else {}
|
if diff_total is not None:
|
||||||
if diff_results is not None:
|
diff_r = diff_total
|
||||||
diff_total = fold(diff_results, by=[], fields=fields, ops=ops)
|
|
||||||
diff_r = diff_total[0] if diff_total else {}
|
|
||||||
ratios = [types[k].ratio(r.get(k), diff_r.get(k))
|
ratios = [types[k].ratio(r.get(k), diff_r.get(k))
|
||||||
for k in fields]
|
for k in fields]
|
||||||
|
|
||||||
@@ -516,8 +536,8 @@ def table(results, diff_results=None, *,
|
|||||||
if k in r else types[k].diff_none
|
if k in r else types[k].diff_none
|
||||||
for k in fields),
|
for k in fields),
|
||||||
' (%s)' % ', '.join(
|
' (%s)' % ', '.join(
|
||||||
'+∞%' if t == float('+inf')
|
'+∞%' if t == +m.inf
|
||||||
else '-∞%' if t == float('-inf')
|
else '-∞%' if t == -m.inf
|
||||||
else '%+.1f%%' % (100*t)
|
else '%+.1f%%' % (100*t)
|
||||||
for t in ratios)))
|
for t in ratios)))
|
||||||
else:
|
else:
|
||||||
@@ -532,8 +552,8 @@ def table(results, diff_results=None, *,
|
|||||||
if k in r or k in diff_r else types[k].diff_none
|
if k in r or k in diff_r else types[k].diff_none
|
||||||
for k in fields),
|
for k in fields),
|
||||||
' (%s)' % ', '.join(
|
' (%s)' % ', '.join(
|
||||||
'+∞%' if t == float('+inf')
|
'+∞%' if t == +m.inf
|
||||||
else '-∞%' if t == float('-inf')
|
else '-∞%' if t == -m.inf
|
||||||
else '%+.1f%%' % (100*t)
|
else '%+.1f%%' % (100*t)
|
||||||
for t in ratios
|
for t in ratios
|
||||||
if t)
|
if t)
|
||||||
@@ -597,9 +617,13 @@ def main(csv_paths, *,
|
|||||||
by, fields, types, results = homogenize(results,
|
by, fields, types, results = homogenize(results,
|
||||||
by=by, fields=fields, renames=renames, define=define)
|
by=by, fields=fields, renames=renames, define=define)
|
||||||
|
|
||||||
|
# fold for total, note we do this with the raw data to avoid
|
||||||
|
# issues with lossy operations
|
||||||
|
total = fold(results, fields=fields, ops=ops)
|
||||||
|
total = total[0] if total else {}
|
||||||
|
|
||||||
# fold to remove duplicates
|
# fold to remove duplicates
|
||||||
results = fold(results,
|
types_, results = fold(results, by=by, fields=fields, types=types, ops=ops)
|
||||||
by=by, fields=fields, ops=ops)
|
|
||||||
|
|
||||||
# write results to CSV
|
# write results to CSV
|
||||||
if args.get('output'):
|
if args.get('output'):
|
||||||
@@ -624,19 +648,25 @@ def main(csv_paths, *,
|
|||||||
_, _, _, diff_results = homogenize(diff_results,
|
_, _, _, diff_results = homogenize(diff_results,
|
||||||
by=by, fields=fields, renames=renames, define=define, types=types)
|
by=by, fields=fields, renames=renames, define=define, types=types)
|
||||||
|
|
||||||
|
# fold for total, note we do this with the raw data to avoid
|
||||||
|
# issues with lossy operations
|
||||||
|
diff_total = fold(diff_results, fields=fields, ops=ops)
|
||||||
|
diff_total = diff_total[0] if diff_total else {}
|
||||||
|
|
||||||
# fold to remove duplicates
|
# fold to remove duplicates
|
||||||
diff_results = fold(diff_results,
|
diff_results = fold(diff_results, by=by, fields=fields, ops=ops)
|
||||||
by=by, fields=fields, ops=ops)
|
|
||||||
|
|
||||||
# print table
|
# print table
|
||||||
if not args.get('quiet'):
|
if not args.get('quiet'):
|
||||||
table(
|
table(
|
||||||
results,
|
results,
|
||||||
|
total,
|
||||||
diff_results if args.get('diff') else None,
|
diff_results if args.get('diff') else None,
|
||||||
|
diff_total if args.get('diff') else None,
|
||||||
by=by,
|
by=by,
|
||||||
fields=fields,
|
fields=fields,
|
||||||
|
types=types_,
|
||||||
ops=ops,
|
ops=ops,
|
||||||
types=types,
|
|
||||||
**args)
|
**args)
|
||||||
|
|
||||||
|
|
||||||
@@ -685,11 +715,11 @@ if __name__ == "__main__":
|
|||||||
help="Only include rows where this field is this value. May include "
|
help="Only include rows where this field is this value. May include "
|
||||||
"comma-separated options.")
|
"comma-separated options.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--add',
|
'--sum',
|
||||||
action='append',
|
action='append',
|
||||||
help="Add these fields (the default).")
|
help="Add these fields (the default).")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--mul',
|
'--prod',
|
||||||
action='append',
|
action='append',
|
||||||
help="Multiply these fields.")
|
help="Multiply these fields.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
@@ -701,9 +731,21 @@ if __name__ == "__main__":
|
|||||||
action='append',
|
action='append',
|
||||||
help="Take the maximum of these fields.")
|
help="Take the maximum of these fields.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--avg',
|
'--mean',
|
||||||
action='append',
|
action='append',
|
||||||
help="Average these fields.")
|
help="Average these fields.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--stddev',
|
||||||
|
action='append',
|
||||||
|
help="Find the standard deviation of these fields.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--gmean',
|
||||||
|
action='append',
|
||||||
|
help="Find the geometric mean of these fields.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--gstddev',
|
||||||
|
action='append',
|
||||||
|
help="Find the geometric standard deviation of these fields.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-s', '--sort',
|
'-s', '--sort',
|
||||||
action='append',
|
action='append',
|
||||||
|
|||||||
Reference in New Issue
Block a user