1#!/usr/bin/env python
2
3# ULP error plot tool.
4#
5# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6# See https://llvm.org/LICENSE.txt for license information.
7# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8
9import numpy as np
10import matplotlib.pyplot as plt
11import sys
12import re
13
14# example usage:
15# build/bin/ulp -e .0001 log 0.5 2.0 2345678 | math/tools/plot.py
16
17def fhex(s):
18	return float.fromhex(s)
19
20def parse(f):
21	xs = []
22	gs = []
23	ys = []
24	es = []
25	# Has to match the format used in ulp.c
26	r = re.compile(r'[^ (]+\(([^ )]*)\) got ([^ ]+) want ([^ ]+) [^ ]+ ulp err ([^ ]+)')
27	for line in f:
28		m = r.match(line)
29		if m:
30			x = fhex(m.group(1))
31			g = fhex(m.group(2))
32			y = fhex(m.group(3))
33			e = float(m.group(4))
34			xs.append(x)
35			gs.append(g)
36			ys.append(y)
37			es.append(e)
38		elif line.startswith('PASS') or line.startswith('FAIL'):
39			# Print the summary line
40			print(line)
41	return xs, gs, ys, es
42
43def plot(xs, gs, ys, es):
44	if len(xs) < 2:
45		print('not enough samples')
46		return
47	a = min(xs)
48	b = max(xs)
49	fig, (ax0,ax1) = plt.subplots(nrows=2)
50	es = np.abs(es) # ignore the sign
51	emax = max(es)
52	ax0.text(a+(b-a)*0.7, emax*0.8, '%s\n%g'%(emax.hex(),emax))
53	ax0.plot(xs,es,'r.')
54	ax0.grid()
55	ax1.plot(xs,ys,'r.',label='want')
56	ax1.plot(xs,gs,'b.',label='got')
57	ax1.grid()
58	ax1.legend()
59	plt.show()
60
61xs, gs, ys, es = parse(sys.stdin)
62plot(xs, gs, ys, es)
63