| |
|
|
| import sys, os |
| import fortran |
| import clapack_scrub |
|
|
| try: set |
| except NameError: |
| from sets import Set as set |
|
|
| |
| |
| |
| F2C_ARGS = '-A' |
|
|
| |
| |
| HEADER = '''\ |
| /* |
| NOTE: This is generated code. Look in README.python for information on |
| remaking this file. |
| */ |
| #include "f2c.h" |
| |
| #ifdef HAVE_CONFIG |
| #include "config.h" |
| #else |
| extern doublereal slamch_(char *); |
| #define EPSILON slamch_("Epsilon") |
| #define SAFEMINIMUM slamch_("Safe minimum") |
| #define PRECISION slamch_("Precision") |
| #define BASE slamch_("Base") |
| #endif |
| |
| |
| extern doublereal slapy2_(real *, real *); |
| |
| ''' |
|
|
| class FortranRoutine: |
| """Wrapper for a Fortran routine in a file. |
| """ |
| type = 'generic' |
| def __init__(self, name=None, filename=None): |
| self.filename = filename |
| if name is None: |
| root, ext = os.path.splitext(filename) |
| name = root |
| self.name = name |
| self._dependencies = None |
|
|
| def dependencies(self): |
| if self._dependencies is None: |
| deps = fortran.getDependencies(self.filename) |
| self._dependencies = [d.lower() for d in deps] |
| return self._dependencies |
|
|
| class UnknownFortranRoutine(FortranRoutine): |
| """Wrapper for a Fortran routine for which the corresponding file |
| is not known. |
| """ |
| type = 'unknown' |
| def __init__(self, name): |
| FortranRoutine.__init__(self, name=name, filename='<unknown>') |
|
|
| def dependencies(self): |
| return [] |
|
|
| class FortranLibrary: |
| """Container for a bunch of Fortran routines. |
| """ |
| def __init__(self, src_dirs): |
| self._src_dirs = src_dirs |
| self.names_to_routines = {} |
|
|
| def _findRoutine(self, rname): |
| rname = rname.lower() |
| for s in self._src_dirs: |
| ffilename = os.path.join(s, rname + '.f') |
| if os.path.exists(ffilename): |
| return self._newFortranRoutine(rname, ffilename) |
| return UnknownFortranRoutine(rname) |
|
|
| def _newFortranRoutine(self, rname, filename): |
| return FortranRoutine(rname, filename) |
|
|
| def addIgnorableRoutine(self, rname): |
| """Add a routine that we don't want to consider when looking at |
| dependencies. |
| """ |
| rname = rname.lower() |
| routine = UnknownFortranRoutine(rname) |
| self.names_to_routines[rname] = routine |
|
|
| def addRoutine(self, rname): |
| """Add a routine to the library. |
| """ |
| self.getRoutine(rname) |
|
|
| def getRoutine(self, rname): |
| """Get a routine from the library. Will add if it's not found. |
| """ |
| unique = [] |
| rname = rname.lower() |
| routine = self.names_to_routines.get(rname, unique) |
| if routine is unique: |
| routine = self._findRoutine(rname) |
| self.names_to_routines[rname] = routine |
| return routine |
|
|
| def allRoutineNames(self): |
| """Return the names of all the routines. |
| """ |
| return self.names_to_routines.keys() |
|
|
| def allRoutines(self): |
| """Return all the routines. |
| """ |
| return self.names_to_routines.values() |
|
|
| def resolveAllDependencies(self): |
| """Try to add routines to the library to satisfy all the dependencies |
| for each routine in the library. |
| |
| Returns a set of routine names that have the dependencies unresolved. |
| """ |
| done_this = set() |
| last_todo = set() |
| while 1: |
| todo = set(self.allRoutineNames()) - done_this |
| if todo == last_todo: |
| break |
| for rn in todo: |
| r = self.getRoutine(rn) |
| deps = r.dependencies() |
| for d in deps: |
| self.addRoutine(d) |
| done_this.add(rn) |
| last_todo = todo |
| return todo |
|
|
| class LapackLibrary(FortranLibrary): |
| def _newFortranRoutine(self, rname, filename): |
| routine = FortranLibrary._newFortranRoutine(self, rname, filename) |
| if filename.find('BLAS') != -1: |
| routine.type = 'blas' |
| elif rname.startswith('z'): |
| routine.type = 'zlapack' |
| else: |
| routine.type = 'slapack' |
| return routine |
|
|
| def allRoutinesByType(self, typename): |
| routines = [(r.name,r) for r in self.allRoutines() if r.type == typename] |
| routines.sort() |
| return [a[1] for a in routines] |
|
|
| def printRoutineNames(desc, routines): |
| print desc |
| for r in routines: |
| print '\t%s' % r.name |
|
|
| def getLapackRoutines(wrapped_routines, ignores, lapack_dir): |
| blas_src_dir = os.path.join(lapack_dir, 'BLAS', 'SRC') |
| if not os.path.exists(blas_src_dir): |
| blas_src_dir = os.path.join(lapack_dir, 'blas', 'src') |
| lapack_src_dir = os.path.join(lapack_dir, 'SRC') |
| if not os.path.exists(lapack_src_dir): |
| lapack_src_dir = os.path.join(lapack_dir, 'src') |
| library = LapackLibrary([blas_src_dir, lapack_src_dir]) |
|
|
| for r in ignores: |
| library.addIgnorableRoutine(r) |
|
|
| for w in wrapped_routines: |
| library.addRoutine(w) |
|
|
| library.resolveAllDependencies() |
|
|
| return library |
|
|
| def getWrappedRoutineNames(wrapped_routines_file): |
| fo = open(wrapped_routines_file) |
| routines = [] |
| ignores = [] |
| for line in fo: |
| line = line.strip() |
| if not line or line.startswith('#'): |
| continue |
| if line.startswith('IGNORE:'): |
| line = line[7:].strip() |
| ig = line.split() |
| ignores.extend(ig) |
| else: |
| routines.append(line) |
| return routines, ignores |
|
|
| def dumpRoutineNames(library, output_dir): |
| for typename in ['unknown', 'blas', 'slapack', 'zlapack']: |
| routines = library.allRoutinesByType(typename) |
| filename = os.path.join(output_dir, typename + '_routines.lst') |
| fo = open(filename, 'w') |
| for r in routines: |
| deps = r.dependencies() |
| fo.write('%s: %s\n' % (r.name, ' '.join(deps))) |
| fo.close() |
|
|
| def concatenateRoutines(routines, output_file): |
| output_fo = open(output_file, 'w') |
| for r in routines: |
| fo = open(r.filename, 'r') |
| source = fo.read() |
| fo.close() |
| output_fo.write(source) |
| output_fo.close() |
|
|
| class F2CError(Exception): |
| pass |
|
|
| def runF2C(fortran_filename, output_dir): |
| |
| cmd = "f2c %s -d %s %s" % (F2C_ARGS, output_dir, fortran_filename) |
| rc = os.system(cmd) |
| if rc != 0: |
| raise F2CError |
|
|
| def scrubF2CSource(c_file): |
| fo = open(c_file, 'r') |
| source = fo.read() |
| fo.close() |
| source = clapack_scrub.scrubSource(source, verbose=True) |
| fo = open(c_file, 'w') |
| fo.write(HEADER) |
| fo.write(source) |
| fo.close() |
|
|
| def main(): |
| if len(sys.argv) != 4: |
| print 'Usage: %s wrapped_routines_file lapack_dir output_dir' % \ |
| (sys.argv[0],) |
| return |
| wrapped_routines_file = sys.argv[1] |
| lapack_src_dir = sys.argv[2] |
| output_dir = sys.argv[3] |
|
|
| wrapped_routines, ignores = getWrappedRoutineNames(wrapped_routines_file) |
| library = getLapackRoutines(wrapped_routines, ignores, lapack_src_dir) |
|
|
| dumpRoutineNames(library, output_dir) |
|
|
| for typename in ['blas', 'slapack']: |
| print 'creating %s_lite.c ...' % typename |
| routines = library.allRoutinesByType(typename) |
| fortran_file = os.path.join(output_dir, typename+'_lite.f') |
| c_file = fortran_file[:-2] + '.c' |
| concatenateRoutines(routines, fortran_file) |
| try: |
| runF2C(fortran_file, output_dir) |
| except F2CError: |
| print 'f2c failed on %s' % fortran_file |
| break |
| scrubF2CSource(c_file) |
|
|
| if __name__ == '__main__': |
| main() |
|
|