+#! /usr/bin/python
+
+from sys import argv, exit
+from itertools import cycle, izip
+import re as RX
+
+def bad_usage():
+ exit('usage: split-pieces { scaf WD | qf WD/N|WD,WD,... } N N ...')
+
+ARGC = 1
+def getarg(must = True):
+ global ARGC
+ if ARGC < len(argv): ARGC += 1; return argv[ARGC - 1]
+ elif must: bad_usage()
+ else: return None
+
+class ScafConvert (object):
+ def __init__(me, piecewd):
+ me.piecewd = piecewd
+ me.fmt = '0x%%0%dx' % ((piecewd + 3)/4)
+ me.mask = (1 << piecewd) - 1
+ @classmethod
+ def parse(cls):
+ return ScafConvert(int(getarg()))
+ def hack(me, n):
+ nn = []
+ while n:
+ nn.append(me.fmt % (n&me.mask))
+ n >>= me.piecewd
+ return nn
+ def unhack(me, nn):
+ return sum(n << i*me.piecewd for i, n in enumerate(nn))
+
+class QfConvert (object):
+ def __init__(me, p, wdseq):
+ me.p = p
+ me.wdseq = wdseq
+ @classmethod
+ def parse(cls):
+ p = eval(getarg())
+ arg = getarg()
+ if '/' in arg:
+ wd, n = map(int, arg.split('/'))
+ seq = [(wd*(i + 1) + n - 1)/n - (wd*i + n - 1)/n for i in xrange(n)]
+ else:
+ seq = map(int, arg.split(','))
+ print ";; piece widths = %r" % seq
+ return QfConvert(p, seq)
+ def hack(me, n):
+ if 2*n >= me.p: n -= p
+ nn = []
+ wds = cycle(me.wdseq)
+ while n:
+ wd = wds.next()
+ lim = 1 << wd; m = lim - 1
+ d = n&m; n >>= wd
+ if d >= lim/2: d -= lim; n += 1
+ nn.append(str(d))
+ return nn
+ def unhack(me, nn):
+ a = o = 0
+ for n, w in izip(nn, cycle(me.wdseq)):
+ a += n << o
+ o += w
+ if a < 0: a += me.p
+ return a
+
+R_split = RX.compile(r',\s*|\s+')
+def spliteval(arg): return map(eval, R_split.split(arg.strip()))
+
+convmap = { 'scaf': ScafConvert,
+ 'unscaf': ScafConvert,
+ 'qf': QfConvert,
+ 'unqf': QfConvert }
+op = getarg()
+cvt = convmap[op].parse()
+if op.startswith('un'): prepare, conv, format = spliteval, cvt.unhack, str
+else: prepare, conv, format = eval, cvt.hack, lambda vv: ', '.join(vv)
+
+while True:
+ val = getarg(must = False)
+ if val is None: break
+ print format(conv(prepare(val)))