File: gen-libdfp-ulps.py

package info (click to toggle)
libdfp 1.0.13-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 6,320 kB
  • sloc: ansic: 48,835; sh: 6,219; asm: 1,911; makefile: 566; awk: 455; python: 396; cpp: 254
file content (107 lines) | stat: -rwxr-xr-x 2,938 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/usr/bin/env python3

import sys
import os
from optparse import OptionParser

class ULP (object):
  def __init__ (self, function, input):
    self.function = function
    self.input = input
    self.ulp32 = 0
    self.ulp64 = 0
    self.ulp128 = 0

  def callstr (self):
    return "\"%s (%s)\"" % (self.function, self.input)

# Parse a ulp description file returning a set of (ulps) for each operation.
# Lines starting with '#' are ignored.
# Each test is decribed as:
# test <function name> <input>
# decimal<N> <ulp expected>
#
# If not described, ULP is assumed to be 0.
def parse_file (filename):
  try:
    ulp = None
    ulps = []
    for line in open(filename, 'r').readlines():
      # Ignore comments and blank lines
      if line.rstrip().startswith ("#"):
        continue
      fields = line.split()
      if len(fields) is 0:
        continue
      if fields[0] == 'test':
        ulp = ULP (fields[1], fields[2])
        ulps.append (ulp)
      elif fields[0] == 'decimal32':
        ulp.ulp32 = fields[1]
      elif fields[0] == 'decimal64':
        ulp.ulp64 = fields[1]
      elif fields[0] == 'decimal128':
        ulp.ulp128 = fields[1]

    return ulps

  except (IOError, OSError) as e:
    print ("error: open (%s) failed: %s\n" % (filename, e.strerror))
    exit (1)


def print_header (filename):
  print ("/* This file is automatically generated")
  print (" * from %s with gen-libdfp-ulps.py.  */" % filename)
  print ("")
  print ("#if defined(DECIMAL32)")
  print ("# define CHOOSE(decimal128, decimal64, decimal32) decimal32")
  print ("#elif defined(DECIMAL64)")
  print ("# define CHOOSE(decimal128, decimal64, decimal32) decimal64")
  print ("#elif defined(DECIMAL128)")
  print ("# define CHOOSE(decimal128, decimal64, decimal32) decimal128")
  print ("#endif")
  print ("")
  print ("struct ulp_data {")
  print ("  const char *name;")
  print ("  FLOAT max_ulp;")
  print ("};")
  print ("")


def print_ulps (ulps):
  print ("/* Maximal error of functions.  */")
  print ("static const struct ulp_data test_ulps[] = {")
  # The array will be used in a bsearch call, so the itens must be sorted
  for ulp in sorted(ulps, key=lambda x: x.callstr()):
    print ("  { %s, CHOOSE(%s, %s, %s) }," %
      (ulp.callstr(), ulp.ulp128, ulp.ulp64, ulp.ulp32))
  print ("};")
    

def print_output (filename):
  ulps = parse_file (filename)
  print_header (filename)
  print_ulps (ulps)


if __name__ == "__main__":
  parser = OptionParser ()
  parser.add_option ("-o", "--output", dest="filename",
                     help="white output to FILE")
  (options, args) = parser.parse_args()

  try:
    if options.filename:
      sys.stdout = open (options.filename, "w")

    if len(args) == 0:
      sys.stderr.write ("usage: gen-libdfp-ulps.py <options> <input file>\n")
      raise Exception()

    print_output (args[0])

  except:
    if options.filename:
      os.remove (options.filename)
    exit (1)