aboutsummaryrefslogtreecommitdiff
path: root/measurements/tolatex.py
diff options
context:
space:
mode:
Diffstat (limited to 'measurements/tolatex.py')
-rw-r--r--measurements/tolatex.py233
1 files changed, 0 insertions, 233 deletions
diff --git a/measurements/tolatex.py b/measurements/tolatex.py
deleted file mode 100644
index f85ee41af..000000000
--- a/measurements/tolatex.py
+++ /dev/null
@@ -1,233 +0,0 @@
-# Generates benchmark graphs in LaTex (following format from the pgfplots
-# package)
-import sys, math, re
-
-USAGE = "USAGE: python tolatex.py [input file] {plot32, plot64, table32, table64}"
-
-SETUPS = {
- "gmpxx": "color=red,mark=x",
- "gmpsec" : "color=red,mark=*",
- "gmpvar": "color=red,mark=o",
- "fiat_montgomery": "color=blue,mark=triangle*",
- "fiat_solinas": "color=blue,mark=triangle",
- }
-
-# setups to combine and functions to combine them
-COMBINE = [
- ("fiat_montgomery", "fiat_solinas", min),
- ]
-
-# setups to exclude
-EXCLUDE = [
- "gmpxx"
- ]
-
-LEGEND = {
- "fiat_montgomery": "this paper",
- "fiat_solinas": "this paper",
- "gmpvar": "GMP mpn API",
- "gmpxx": "GMP C++ API",
- "gmpsec" : "GMP mpn_sec API"
- }
-
-class ParseException(Exception): pass
-class MissingDataException(Exception): pass
-
-# given a string representing one term or "tap" in a prime, returns a pair of
-# integers representing the weight and coefficient of that tap
-# "2 ^ y" -> [1, y]
-# "x * 2 ^ y" -> [x, y]
-# "x * y" -> [x*y,0]
-# "x" -> [x,0]
-def parse_term(t) :
- if "*" not in t and "^" not in t:
- return [int(t),0]
-
- if "*" in t:
- if len(t.split("*")) > 2: # this occurs when e.g. [w - x * y] has been turned into [w + -1 * x * y]
- a1,a2,b = t.split("*")
- a = int(a1) * int(a2)
- else:
- a,b = t.split("*")
- if "^" not in b:
- return [int(a) * int(b),0]
- else:
- a,b = (1,t)
-
- b,e = b.split("^")
- if int(b) != 2:
- raise ParseException("Could not parse term, power with base other than 2: %s" %t)
- return [int(a),int(e)]
-
-# expects prime to be a string and expressed as sum/difference of products of
-# two with small coefficients (e.g. '2^448 - 2^224 - 1', '2^255 - 19')
-# returns tuple (string representation, numeric value)
-def parse_prime(prime):
- rep = prime.replace("e", "^").replace("m", "-").replace("p","+").replace("x","*")
- terms = rep.replace("-", "+ -").replace(' ', '').replace('+-2^', '+-1*2^').split("+")
- value = sum([(x * (2**e)) for x,e in map(parse_term, terms)])
- return (rep, value)
-
-def parse_line(line):
- data = line.strip().split("\t")
- if len(data) != 3 or (data[1] not in SETUPS) or ("2e" not in data[0]) :
- raise ParseException("Could not parse line %s" %line.strip())
- return {
- "prime" : data[0],
- "setup" : data[1],
- "time" : data[2] }
-
-def final_lines(bits):
- out = []
- for s in SETUPS:
- if (s in EXCLUDE) or any([x[1]==s for x in COMBINE]):
- continue # in this case, the setup has been combined into some other one
- out.append(s)
- return out
-
-# check for missing data points
-def check_missing(data, bits):
- all_primes = set()
- for s in final_lines(bits):
- all_primes = all_primes | set(data[s].keys())
- missing = []
- for s in final_lines(bits):
- x = all_primes ^ set(data[s].keys())
- if len(x) != 0:
- missing.append((s, x))
- if len(missing) > 0:
- message = "\n".join(["missing datapoints in %s: primes are %s" %(LEGEND[s],list(map(lambda t:t[0], x))) for s,x in missing])
- print("WARNING: %s" %message)
- #raise MissingDataException(message)
-
-# reorganize, and parse primes
-def clean_plot_data(parsed_lines, bits):
- out = {s:{} for s in SETUPS}
- for ln in parsed_lines:
- p = parse_prime(ln["prime"])
- if p in out[ln["setup"]]:
- out[ln["setup"]][p] = min(float(ln["time"]), out[ln["setup"]][p])
- else:
- out[ln["setup"]][p] = float(ln["time"])
- # combine setups according to COMBINE list
- for s1, s2, f in COMBINE:
- all_primes = list(out[s1].keys())
- all_primes.extend(out[s2].keys())
- for p in set(all_primes):
- if p in out[s1] and p in out[s2]:
- out[s1][p] = f(out[s1][p], out[s2][p])
- elif p in out[s2]:
- out[s1][p] = out[s2][p]
- check_missing(out, bits)
- return out
-
-# remove duplicates, reorganize, and parse primes
-def clean_table_data(parsed_lines):
- all_primes = set([ln["prime"] for ln in parsed_lines])
- out = {p:{} for p in all_primes}
- for ln in parsed_lines:
- prime = ln["prime"]
- s = ln["setup"]
- if s in out[prime]:
- out[prime][s] = min(float(ln["time"]), out[prime][s])
- else:
- out[prime][s] = float(ln["time"])
- return out
-
-def maketable(data, bits):
- if bits == 64:
- out="""\\tablehead{%
- \\hline
- & \\multicolumn{2}{c|}{\\textbf{Our Code}} & \\multicolumn{3}{c|}{\\textbf{GMP Code}} & \\\\
- \\cline{2-6}
- \\textbf{Prime} & \\textbf{Sol.} & \\textbf{Mont.} & \\textbf{const time} & \\textbf{var time} & \\textbf{C++} & \\textbf{Speedup} \\\\ \\hline}
-\\footnotesize
-\\begin{xtabular}{|l|p{0.6cm}|p{0.6cm}|p{0.6cm}|p{0.6cm}|p{0.6cm}|p{0.6cm}|}\n"""
- else:
- out="""\\tablehead{%
- \\hline
- & \\multicolumn{2}{c|}{\\textbf{Our Code}} & \\multicolumn{2}{c|}{\\textbf{GMP Code}} & \\\\
- \\cline{2-5}
- \\textbf{Prime} & \\textbf{Solinas} & \\textbf{Mont.} & \\textbf{const time} & \\textbf{var time} & \\textbf{Speedup} \\\\ \\hline}
-\\footnotesize
-\\begin{xtabular}{|l|p{0.7cm}|p{0.7cm}|p{0.7cm}|p{0.7cm}|p{0.9cm}|}\n"""
-
- cols_64 = ["fiat_solinas", "fiat_montgomery", "gmpsec", "gmpvar", "gmpxx"]
- cols_32 = ["fiat_solinas", "fiat_montgomery", "gmpsec", "gmpvar"]
- cols = cols_64 if bits == 64 else cols_32
-
- for p in sorted(data.keys()):
- prime_latex= re.sub("2\^[0-9]+", lambda matchobj : "2^{%s}" %matchobj.group(0)[2:], parse_prime(p)[0])
- prime_latex= re.sub("[0-9]\*[0-9]", lambda matchobj : "%s\cdot %s" %(matchobj.group(0)[0], matchobj.group(0)[2]), prime_latex)
- row = ["$" + prime_latex + "$"]
- our_best = None
- gmp_best = None
- for s in cols:
- if s in data[p]:
- row.append(str(data[p][s]))
- if "fiat" in s and (our_best == None or float(data[p][s]) < our_best):
- our_best = float(data[p][s])
- if "gmp" in s and (gmp_best == None or float(data[p][s]) < gmp_best):
- gmp_best = float(data[p][s])
- else:
- row.append("-")
- if our_best != None and gmp_best != None:
- row.append(str(round(gmp_best/our_best, 2)))
- else:
- row.append("-")
- out += ("\t" + " & ".join(row) + " \\\\ \n")
-
- out +="""\\hline\n\\end{xtabular}"""
- return out
-
-def makeplot(data, bits):
- out = """
- \\begin{figure*}
- \\begin{tikzpicture}
- \t\\begin{axis}[
- \t\theight=3.4cm,
- \t\ttitle style={font=\small},
- \t\ttitle=%s-Bit Field Arithmetic Benchmarks,
- \t\twidth=\\textwidth,
- \t\tlegend pos= north west,
- \t\txtick distance=64,
- \t\tlegend style={font=\\tiny},
- \t\tlabel style={font=\\footnotesize},
- \t\txlabel style={at={(0.5,0.1)}, anchor=north},
- \t\tlegend columns=2,
- \t\ttick label style={font=\\footnotesize},
- \t\tgrid=major,
- \t\tymin=0,
- \t\txlabel=log2(prime),
- \t\tylabel=Time (seconds)]\n""" %bits
- for s in final_lines(bits):
- out +="\t\t\\addplot[%s,mark size=2pt] coordinates {\n" %SETUPS[s]
- for p,t in sorted(data[s].items()):
- out += "\t\t\t(%s, %s) \n" %(math.log2(p[1]), t)
- out += "\t\t};\n"
- out += "\t\t\\addlegendentry{%s}\n\n" %LEGEND[s].replace("_", "\_")
- out += "\t\end{axis}\n\\end{tikzpicture}\n\\end{figure*}"
- return out
-
-if __name__ == "__main__":
- if len(sys.argv) != 3 or sys.argv[2] not in ["plot32", "plot64", "table32", "table64"]:
- print(USAGE)
- sys.exit()
- f = open(sys.argv[1])
- parsed_lines = []
- for line in f:
- try:
- parsed_lines.append(parse_line(line))
- except ParseException:
- print("WARNING: Could not parse line %s, skipping" %line.strip().split("\t"))
- f.close()
-
- if sys.argv[2] == "table32":
- print(maketable(clean_table_data(parsed_lines), 32))
- if sys.argv[2] == "table64":
- print(maketable(clean_table_data(parsed_lines), 64))
- elif sys.argv[2] == "plot32":
- print(makeplot(clean_plot_data(parsed_lines, 32), 32))
- elif sys.argv[2] == "plot64":
- print(makeplot(clean_plot_data(parsed_lines, 64), 64))
-