summaryrefslogtreecommitdiff
path: root/utils/ABITest/Enumeration.py
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-01-15 04:24:17 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-01-15 04:24:17 +0000
commita83fb8647bfca3aa9bd7049f817979f092244e83 (patch)
tree58b787c6864824712df6a044f818e882be63330c /utils/ABITest/Enumeration.py
parent4bb64e77dd3b22070e28b7f9ff99feb576eaf6ef (diff)
downloadclang-a83fb8647bfca3aa9bd7049f817979f092244e83.tar.gz
Add utils/ABITest, my ABI test generation tool.
- Mostly written as an entertaining exercise in enumerating large or (countably, naturally) infinite sets. But hey, its useful too! - Idea is to number all C-types so that the N-th type can quickly be computed, with a good deal of flexibility about what types to include, and taking some care so that the (N+1)-th type is interestingly different from the N-th type. For example, using the default generator, the 1,000,000-th function type is: -- typedef _Complex int T0; typedef char T1 __attribute__ ((vector_size (4))); typedef int T2 __attribute__ ((vector_size (4))); T2 fn1000000(T0 arg0, signed long long arg1, T1 arg2, T0 arg3); -- and the 1,000,001-th type is: -- typedef _Complex char T0; typedef _Complex char T2; typedef struct T1 { T2 field0; T2 field1; T2 field2; } T1; typedef struct T3 { } T3; unsigned short fn1000001(T0 arg0, T1 arg1, T3 arg2); -- Computing the 10^1600-th type takes a little less than 1s. :) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62253 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/ABITest/Enumeration.py')
-rw-r--r--utils/ABITest/Enumeration.py276
1 files changed, 276 insertions, 0 deletions
diff --git a/utils/ABITest/Enumeration.py b/utils/ABITest/Enumeration.py
new file mode 100644
index 0000000000..47e47026db
--- /dev/null
+++ b/utils/ABITest/Enumeration.py
@@ -0,0 +1,276 @@
+"""Utilities for enumeration of finite and countably infinite sets.
+"""
+###
+# Countable iteration
+
+# Simplifies some calculations
+class Aleph0(int):
+ _singleton = None
+ def __new__(type):
+ if type._singleton is None:
+ type._singleton = int.__new__(type)
+ return type._singleton
+ def __repr__(self): return '<aleph0>'
+ def __str__(self): return 'inf'
+
+ def __cmp__(self, b):
+ return 1
+
+ def __sub__(self, b):
+ raise ValueError,"Cannot subtract aleph0"
+ __rsub__ = __sub__
+
+ def __add__(self, b):
+ return self
+ __radd__ = __add__
+
+ def __mul__(self, b):
+ if b == 0: return b
+ return self
+ __rmul__ = __mul__
+
+ def __floordiv__(self, b):
+ if b == 0: raise ZeroDivisionError
+ return self
+ __rfloordiv__ = __floordiv__
+ __truediv__ = __floordiv__
+ __rtuediv__ = __floordiv__
+ __div__ = __floordiv__
+ __rdiv__ = __floordiv__
+
+ def __pow__(self, b):
+ if b == 0: return 1
+ return self
+aleph0 = Aleph0()
+
+def base(line):
+ return line*(line+1)//2
+
+def pairToN((x,y)):
+ line,index = x+y,y
+ return base(line)+index
+
+def getNthPairInfo(N):
+ # Avoid various singularities
+ if N==0:
+ return (0,0)
+
+ # Gallop to find bounds for line
+ line = 1
+ next = 2
+ while base(next)<=N:
+ line = next
+ next = line << 1
+
+ # Binary search for starting line
+ lo = line
+ hi = line<<1
+ while lo + 1 != hi:
+ #assert base(lo) <= N < base(hi)
+ mid = (lo + hi)>>1
+ if base(mid)<=N:
+ lo = mid
+ else:
+ hi = mid
+
+ line = lo
+ return line, N - base(line)
+
+def getNthPair(N):
+ line,index = getNthPairInfo(N)
+ return (line - index, index)
+
+def getNthPairBounded(N,W=aleph0,H=aleph0,useDivmod=False):
+ """getNthPairBounded(N, W, H) -> (x, y)
+
+ Return the N-th pair such that 0 <= x < W and 0 <= y < H."""
+
+ if W <= 0 or H <= 0:
+ raise ValueError,"Invalid bounds"
+ elif N >= W*H:
+ raise ValueError,"Invalid input (out of bounds)"
+
+ # Simple case...
+ if W is aleph0 and H is aleph0:
+ return getNthPair(N)
+
+ # Otherwise simplify by assuming W < H
+ if H < W:
+ x,y = getNthPairBounded(N,H,W,useDivmod=useDivmod)
+ return y,x
+
+ if useDivmod:
+ return N%W,N//W
+ else:
+ # Conceptually we want to slide a diagonal line across a
+ # rectangle. This gives more interesting results for large
+ # bounds than using divmod.
+
+ # If in lower left, just return as usual
+ cornerSize = base(W)
+ if N < cornerSize:
+ return getNthPair(N)
+
+ # Otherwise if in upper right, subtract from corner
+ if H is not aleph0:
+ M = W*H - N - 1
+ if M < cornerSize:
+ x,y = getNthPair(M)
+ return (W-1-x,H-1-y)
+
+ # Otherwise, compile line and index from number of times we
+ # wrap.
+ N = N - cornerSize
+ index,offset = N%W,N//W
+ # p = (W-1, 1+offset) + (-1,1)*index
+ return (W-1-index, 1+offset+index)
+def getNthPairBoundedChecked(N,W=aleph0,H=aleph0,useDivmod=False,GNP=getNthPairBounded):
+ x,y = GNP(N,W,H,useDivmod)
+ assert 0 <= x < W and 0 <= y < H
+ return x,y
+
+def getNthNTuple(N, W, H=aleph0, useLeftToRight=False):
+ """getNthNTuple(N, W, H) -> (x_0, x_1, ..., x_W)
+
+ Return the N-th W-tuple, where for 0 <= x_i < H."""
+
+ if useLeftToRight:
+ elts = [None]*W
+ for i in range(W):
+ elts[i],N = getNthPairBounded(N, H)
+ return tuple(elts)
+ else:
+ if W==0:
+ return ()
+ elif W==1:
+ return (N,)
+ elif W==2:
+ return getNthPairBounded(N, H, H)
+ else:
+ LW,RW = W//2, W - (W//2)
+ L,R = getNthPairBounded(N, H**LW, H**RW)
+ return (getNthNTuple(L,LW,H=H,useLeftToRight=useLeftToRight) +
+ getNthNTuple(R,RW,H=H,useLeftToRight=useLeftToRight))
+def getNthNTupleChecked(N, W, H=aleph0, useLeftToRight=False, GNT=getNthNTuple):
+ t = GNT(N,W,H,useLeftToRight)
+ assert len(t) == W
+ for i in t:
+ assert i < H
+ return t
+
+def getNthTuple(N, maxSize=aleph0, maxElement=aleph0, useDivmod=False, useLeftToRight=False):
+ """getNthTuple(N, maxSize, maxElement) -> x
+
+ Return the N-th tuple where len(x) < maxSize and for y in x, 0 <=
+ y < maxElement."""
+
+ # All zero sized tuples are isomorphic, don't ya know.
+ if N == 0:
+ return ()
+ N -= 1
+ if maxElement is not aleph0:
+ if maxSize is aleph0:
+ raise NotImplementedError,'Max element size without max size unhandled'
+ bounds = [maxElement**i for i in range(1, maxSize+1)]
+ S,M = getNthPairVariableBounds(N, bounds)
+ else:
+ S,M = getNthPairBounded(N, maxSize, useDivmod=useDivmod)
+ return getNthNTuple(M, S+1, maxElement, useLeftToRight=useLeftToRight)
+def getNthTupleChecked(N, maxSize=aleph0, maxElement=aleph0,
+ useDivmod=False, useLeftToRight=False, GNT=getNthTuple):
+ # FIXME: maxsize is inclusive
+ t = GNT(N,maxSize,maxElement,useDivmod,useLeftToRight)
+ assert len(t) <= maxSize
+ for i in t:
+ assert i < maxElement
+ return t
+
+def getNthPairVariableBounds(N, bounds):
+ """getNthPairVariableBounds(N, bounds) -> (x, y)
+
+ Given a finite list of bounds (which may be finite or aleph0),
+ return the N-th pair such that 0 <= x < len(bounds) and 0 <= y <
+ bounds[x]."""
+
+ if not bounds:
+ raise ValueError,"Invalid bounds"
+ if not (0 <= N < sum(bounds)):
+ raise ValueError,"Invalid input (out of bounds)"
+
+ level = 0
+ active = range(len(bounds))
+ active.sort(key=lambda i: bounds[i])
+ prevLevel = 0
+ for i,index in enumerate(active):
+ level = bounds[index]
+ W = len(active) - i
+ if level is aleph0:
+ H = aleph0
+ else:
+ H = level - prevLevel
+ levelSize = W*H
+ if N<levelSize: # Found the level
+ idelta,delta = getNthPairBounded(N, W, H)
+ return active[i+idelta],prevLevel+delta
+ else:
+ N -= levelSize
+ prevLevel = level
+ else:
+ raise RuntimError,"Unexpected loop completion"
+
+def getNthPairVariableBoundsChecked(N, bounds, GNVP=getNthPairVariableBounds):
+ x,y = GNVP(N,bounds)
+ assert 0 <= x < len(bounds) and 0 <= y < bounds[x]
+ return (x,y)
+
+###
+
+def testPairs():
+ W = 3
+ H = 6
+ a = [[' ' for x in range(10)] for y in range(10)]
+ b = [[' ' for x in range(10)] for y in range(10)]
+ for i in range(min(W*H,40)):
+ x,y = getNthPairBounded(i,W,H)
+ x2,y2 = getNthPairBounded(i,W,H,useDivmod=True)
+ print i,(x,y),(x2,y2)
+ a[y][x] = '%2d'%i
+ b[y2][x2] = '%2d'%i
+
+ print '-- a --'
+ for ln in a[::-1]:
+ if ''.join(ln).strip():
+ print ' '.join(ln)
+ print '-- b --'
+ for ln in b[::-1]:
+ if ''.join(ln).strip():
+ print ' '.join(ln)
+
+def testPairsVB():
+ bounds = [2,2,4,aleph0,5,aleph0]
+ a = [[' ' for x in range(15)] for y in range(15)]
+ b = [[' ' for x in range(15)] for y in range(15)]
+ for i in range(min(sum(bounds),40)):
+ x,y = getNthPairVariableBounds(i, bounds)
+ print i,(x,y)
+ a[y][x] = '%2d'%i
+
+ print '-- a --'
+ for ln in a[::-1]:
+ if ''.join(ln).strip():
+ print ' '.join(ln)
+
+###
+
+# Toggle to use checked versions of enumeration routines.
+if False:
+ getNthPairVariableBounds = getNthPairVariableBoundsChecked
+ getNthPairBounded = getNthPairBoundedChecked
+ getNthNTuple = getNthNTupleChecked
+ getNthTuple = getNthTupleChecked
+
+if __name__ == '__main__':
+ testPairs()
+
+ testPairsVB()
+