1+ #!/usr/bin/env python3
2+
3+ import sys
4+ import re
5+ import argparse
6+
7+ # Function to format a number to two significant digits
8+ def format_to_two_sig_digits (value ):
9+ if not isinstance (value , (int , float )) or value == 0 :
10+ return "N/A"
11+
12+ # Handle negative numbers
13+ is_negative = value < 0
14+ abs_value = abs (value )
15+
16+ exponent = 0
17+
18+ while abs_value >= 100 :
19+ abs_value /= 10
20+ exponent += 1
21+ while abs_value < 10 :
22+ abs_value *= 10
23+ exponent -= 1
24+
25+ # Round to two significant digits
26+ abs_value = round (abs_value , 0 )
27+
28+ # Format the number
29+ if exponent >= 0 and exponent <= 4 :
30+ format = f"{ '-' if is_negative else '' } { abs_value * 10 ** exponent } "
31+ format = format .replace (".0" , "" )
32+ return format
33+ elif exponent < 0 and exponent >= - 4 :
34+ return f"{ '-' if is_negative else '' } { abs_value * 10 ** exponent :.1f} "
35+ else :
36+ return f"{ '-' if is_negative else '' } { abs_value :.1f} e{ exponent } "
37+
38+ # Function to parse the raw input data
39+ def parse_input (data ):
40+ lines = data .splitlines ()
41+ parsed_data = []
42+ current_entry = None
43+
44+ for line in lines :
45+ line = line .strip ()
46+ print (f"Processing line: { line } " ) # Debugging output
47+ # Skip empty lines or comments
48+ if not line or line .startswith ("#" ):
49+ continue
50+
51+ # Match lines that start a new entry (e.g., "just_string : 1365.92 MB/s ...")
52+ match_entry = re .match (r"(\S+)\s*:\s*[\d.]+\s*MB/s" , line )
53+ if match_entry :
54+ print (f"Found new entry: { match_entry .group (1 )} " ) # Debugging output
55+ current_entry = {"name" : match_entry .group (1 )}
56+ parsed_data .append (current_entry )
57+ if not current_entry :
58+ continue
59+ print (f"reviewing line { line } " ) # Debugging output
60+
61+ # Match lines with ns/f
62+ match_ns = re .search (r"([\d.]+)\s*ns/f" , line )
63+ if match_ns and current_entry :
64+ print (f"Found ns/f: { match_ns .group (1 )} " )
65+ current_entry ["ns_per_float" ] = float (match_ns .group (1 ))
66+
67+ # Match lines with instructions/float (i/f)
68+ match_inst_float = re .search (r"([\d.]+)\s*i/f" , line )
69+ if match_inst_float and current_entry :
70+ print (f"Found i/f: { match_inst_float .group (1 )} " )
71+ current_entry ["inst_per_float" ] = float (match_inst_float .group (1 ))
72+
73+ # Match lines with instructions/cycle (i/c)
74+ match_inst_cycle = re .search (r"([\d.]+)\s*i/c" , line )
75+ if match_inst_cycle and current_entry :
76+ print (f"Found i/c: { match_inst_cycle .group (1 )} " )
77+ current_entry ["inst_per_cycle" ] = float (match_inst_cycle .group (1 ))
78+
79+ # Filter out incomplete entries
80+ return parsed_data
81+
82+ # Function to generate LaTeX table
83+ def generate_latex_table (data ):
84+ latex_table = r"""
85+ \begin{tabular}{lccc}
86+ \toprule
87+ \textbf{Name} & \textbf{ns/f} & \textbf{instructions/float} & \textbf{instructions/cycle} \\
88+ \midrule
89+ """
90+
91+ for entry in data :
92+ name = entry ["name" ].replace ("_" , "\\ _" ) # Escape underscores for LaTeX
93+ ns_per_float = format_to_two_sig_digits (entry ['ns_per_float' ]) if 'ns_per_float' in entry else 'N/A'
94+ inst_per_float = format_to_two_sig_digits (entry ['inst_per_float' ]) if 'inst_per_float' in entry else 'N/A'
95+ inst_per_cycle = format_to_two_sig_digits (entry ['inst_per_cycle' ]) if 'inst_per_cycle' in entry else 'N/A'
96+ latex_table += f"{ name } & { ns_per_float } & { inst_per_float } & { inst_per_cycle } \\ \\ \n "
97+
98+ latex_table += r"""\bottomrule
99+ \end{tabular}
100+ """
101+ return latex_table
102+
103+ if __name__ == "f__main__" :
104+ print (format_to_two_sig_digits (336.0 ))
105+
106+
107+ if __name__ == "__main__" :
108+ parser = argparse .ArgumentParser (description = "Generate LaTeX table from performance data" )
109+ parser .add_argument ("file" , nargs = "?" , help = "Optional input file name (if not provided, reads from stdin)" )
110+ args = parser .parse_args ()
111+
112+ # Read input data
113+ if args .file :
114+ try :
115+ with open (args .file , "r" ) as f :
116+ raw_input = f .read ()
117+ except FileNotFoundError :
118+ print (f"Error: File '{ args .file } ' not found." , file = sys .stderr )
119+ sys .exit (1 )
120+ except IOError as e :
121+ print (f"Error reading file '{ args .file } ': { e } " , file = sys .stderr )
122+ sys .exit (1 )
123+ else :
124+ raw_input = sys .stdin .read ()
125+ parsed_data = parse_input (raw_input )
126+ print (f"Parsed data: { parsed_data } " ) # Debugging output
127+ latex_output = generate_latex_table (parsed_data )
128+ print (latex_output )
0 commit comments