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