File: header_gen.py

package info (click to toggle)
lapackpp 2024.10.26-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,500 kB
  • sloc: cpp: 80,181; ansic: 27,660; python: 4,838; xml: 182; perl: 99; makefile: 53; sh: 23
file content (161 lines) | stat: -rwxr-xr-x 6,075 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/env python3

'''
Generate C prototypes for the LAPACK Fortran functions by parsing
doxygen comments in LAPACK's SRC *.f files. Looks for routines in
LAPACK's SRC, INSTALL, and MATGEN directories. (Because MATGEN is the
last directory checked, error messages show that file not found.)

Example usage:

    # Assumes $LAPACKDIR is set
    lapackpp> echo $LAPACKDIR
    /Users/mgates/Documents/lapack

    lapackpp> ./tools/header_gen.py {s,d,c,z}posv {s,d}ormqr {c,z}unmqr
    generating gen/fortran.h

    lapackpp> ./tools/header_gen.py all
    reading include/lapack/fortran.h to re-generate all prototypes
    generating gen/fortran.h
    // skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/slassq.f
    // skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/dlassq.f
    // skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/classq.f
    // skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/zlassq.f
    // skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/slartg.f
    // skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/dlartg.f
    // skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/clartg.f
    // skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/zlartg.f
'''

from __future__ import print_function

import sys
import re
import os

lapack = os.environ['LAPACKDIR']

if (len( sys.argv ) == 1):
    print( 'Usage:', sys.argv[0], '[routine ...]\n' +
           '      ', sys.argv[0], 'all\n' +
           'See script for more details' )
    exit(1)
# end

if (sys.argv[1] == 'all'):
    #header = lapack + '/LAPACKE/include/lapack.h'
    header = 'include/lapack/fortran.h'
    print( 'reading', header, 'to re-generate all prototypes' )
    funcs = []
    f = open( header )
    for line in f:
        s = re.search( r' +LAPACK_(\w+) +LAPACK_GLOBAL\( *\1', line )
        #s = re.search( r'(?:void|float|double) +LAPACK_GLOBAL\((\w+),', line )
        if (s):
            funcs.append( s.group(1) )
    # end
else:
    funcs = sys.argv[1:]
# end

output = 'gen/fortran.h'
print( 'generating', output )
output = open( output, 'w' )

intent = None
var    = None
vtype  = None
dtype  = None

typemap = {
    'character'        : 'char',
    'integer'          : 'lapack_int',
    'real'             : 'float',
    'double precision' : 'double',
    'complex'          : 'lapack_complex_float',
    'complex*16'       : 'lapack_complex_double',
    'logical'          : 'lapack_logical',

    'logical function of two real arguments'               : 'LAPACK_S_SELECT2',
    'logical function of three real arguments'             : 'LAPACK_S_SELECT3',

    'logical function of two double precision arguments'   : 'LAPACK_D_SELECT2',
    'logical function of three double precision arguments' : 'LAPACK_D_SELECT3',

    'logical function of one complex argument'     : 'LAPACK_C_SELECT1',
    'logical function of two complex arguments'    : 'LAPACK_C_SELECT2',

    'logical function of one complex*16 argument'  : 'LAPACK_Z_SELECT1',
    'logical function of two complex*16 arguments' : 'LAPACK_Z_SELECT2',
}

for func in funcs:
    s = re.search( '\.f', func )
    if (s):
        filename = func
    else:
        for subdir in ('SRC', 'INSTALL', 'TESTING/MATGEN'):
            filename = lapack + '/' + subdir + '/' + func + '.f'
            if (os.path.exists( filename )):
                break
            # end
        # end
    # end

    if (os.path.exists( filename )):
        #print( 'read', filename )
        f = open( filename )
        args = []
        retval = 'void'
        for line in f:
            s = re.search( r'^\* +\b(.*)\b +FUNCTION +(\w+)', line )  # \( *(.*) *\)
            if (s):
                retval = typemap[ s.group(1).lower() ]
                continue
            # end

            s = re.search( r'^\*> *\\param\[(in|out|in,out|inout)\] +(\w+)', line )
            if (s):
                intent = s.group(1).lower()
                var    = s.group(2)
                vtype  = var  # vtype used as flag to say we have a variable and are looking for its type
                continue
            # end

            if (vtype):
                s = (re.search( '^\*> *' + vtype + ' +is +(CHARACTER|INTEGER|REAL|DOUBLE PRECISION|COMPLEX\*16|COMPLEX|LOGICAL)( array)?', line ) or
                     re.search( '^\*> *\(workspace\) +(CHARACTER|INTEGER|REAL|DOUBLE PRECISION|COMPLEX\*16|COMPLEX|LOGICAL)( array)?', line ) or
                     re.search( '^\*> *' + vtype + ' +is a (LOGICAL FUNCTION of (?:one|two|three) (?:REAL|DOUBLE PRECISION|COMPLEX\*16|COMPLEX) arguments?)( array)?', line ))
                if (s):
                    dtype = s.group(1).lower()
                    dtype = typemap[dtype]
                    array = s.group(2)
                    vtype = None
                    # leave arrays uppercase, except work and pivots
                    if (array and var not in ('WORK', 'RWORK', 'IWORK', 'IPIV', 'JPIV', 'PIV')):
                        pass #lvar = var
                    else:
                        var = var.lower()
                    if (intent == 'in'):
                        args.append( dtype + ' const* ' + var )
                    else:
                        args.append( dtype + '* ' + var )
                    continue
                # end
            # end
        # end
        print( '#define LAPACK_' + func + ' LAPACK_GLOBAL( ' + func + ', '
               + func.upper() + ' )', file=output )
        print( retval + ' LAPACK_' + func + '(\n    ' + ', '.join( args )
               + '\n);\n', file=output )
    else:
        print( '// skipping, file not found:', filename )
        print( '// skipping, file not found:', filename, file=output )
        print( '// #define LAPACK_' + func + ' LAPACK_GLOBAL(' + func + ','
               + func.upper() + ')', file=output )
        print( '// void LAPACK_' + func + '( ... );\n', file=output )
    # end
# end

output.close()