_cython_signature_generator.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. """
  2. A script that uses f2py to generate the signature files used to make
  3. the Cython BLAS and LAPACK wrappers from the fortran source code for
  4. LAPACK and the reference BLAS.
  5. To generate the BLAS wrapper signatures call:
  6. python _cython_signature_generator.py blas <blas_directory> <out_file>
  7. To generate the LAPACK wrapper signatures call:
  8. python _cython_signature_generator.py lapack <lapack_src_directory> <out_file>
  9. This script expects to be run on the source directory for
  10. the oldest supported version of LAPACK (currently 3.4.0).
  11. """
  12. import glob
  13. import os
  14. from numpy.f2py import crackfortran
  15. sig_types = {'integer': 'int',
  16. 'complex': 'c',
  17. 'double precision': 'd',
  18. 'real': 's',
  19. 'complex*16': 'z',
  20. 'double complex': 'z',
  21. 'character': 'char',
  22. 'logical': 'bint'}
  23. def get_type(info, arg):
  24. argtype = sig_types[info['vars'][arg]['typespec']]
  25. if argtype == 'c' and info['vars'][arg].get('kindselector') is not None:
  26. argtype = 'z'
  27. return argtype
  28. def make_signature(filename):
  29. info = crackfortran.crackfortran(filename)[0]
  30. name = info['name']
  31. if info['block'] == 'subroutine':
  32. return_type = 'void'
  33. else:
  34. return_type = get_type(info, name)
  35. arglist = [' *'.join([get_type(info, arg), arg]) for arg in info['args']]
  36. args = ', '.join(arglist)
  37. # Eliminate strange variable naming that replaces rank with rank_bn.
  38. args = args.replace('rank_bn', 'rank')
  39. return '{0} {1}({2})\n'.format(return_type, name, args)
  40. def get_sig_name(line):
  41. return line.split('(')[0].split(' ')[-1]
  42. def sigs_from_dir(directory, outfile, manual_wrappers=None, exclusions=None):
  43. if directory[-1] in ['/', '\\']:
  44. directory = directory[:-1]
  45. files = sorted(glob.glob(directory + '/*.f*'))
  46. if exclusions is None:
  47. exclusions = []
  48. if manual_wrappers is not None:
  49. exclusions += [get_sig_name(l) for l in manual_wrappers.split('\n')]
  50. signatures = []
  51. for filename in files:
  52. name = os.path.splitext(os.path.basename(filename))[0]
  53. if name in exclusions:
  54. continue
  55. signatures.append(make_signature(filename))
  56. if manual_wrappers is not None:
  57. signatures += [l + '\n' for l in manual_wrappers.split('\n')]
  58. signatures.sort(key=get_sig_name)
  59. comment = ["# This file was generated by _cython_signature_generator.py.\n",
  60. "# Do not edit this file directly.\n\n"]
  61. with open(outfile, 'w') as f:
  62. f.writelines(comment)
  63. f.writelines(signatures)
  64. # slamch and dlamch are not in the lapack src directory, but,since they
  65. # already have Python wrappers, we'll wrap them as well.
  66. # The other manual signatures are used because the signature generating
  67. # functions don't work when function pointer arguments are used.
  68. lapack_manual_wrappers = '''void cgees(char *jobvs, char *sort, cselect1 *select, int *n, c *a, int *lda, int *sdim, c *w, c *vs, int *ldvs, c *work, int *lwork, s *rwork, bint *bwork, int *info)
  69. void cgeesx(char *jobvs, char *sort, cselect1 *select, char *sense, int *n, c *a, int *lda, int *sdim, c *w, c *vs, int *ldvs, s *rconde, s *rcondv, c *work, int *lwork, s *rwork, bint *bwork, int *info)
  70. void cgges(char *jobvsl, char *jobvsr, char *sort, cselect2 *selctg, int *n, c *a, int *lda, c *b, int *ldb, int *sdim, c *alpha, c *beta, c *vsl, int *ldvsl, c *vsr, int *ldvsr, c *work, int *lwork, s *rwork, bint *bwork, int *info)
  71. void cggesx(char *jobvsl, char *jobvsr, char *sort, cselect2 *selctg, char *sense, int *n, c *a, int *lda, c *b, int *ldb, int *sdim, c *alpha, c *beta, c *vsl, int *ldvsl, c *vsr, int *ldvsr, s *rconde, s *rcondv, c *work, int *lwork, s *rwork, int *iwork, int *liwork, bint *bwork, int *info)
  72. void dgees(char *jobvs, char *sort, dselect2 *select, int *n, d *a, int *lda, int *sdim, d *wr, d *wi, d *vs, int *ldvs, d *work, int *lwork, bint *bwork, int *info)
  73. void dgeesx(char *jobvs, char *sort, dselect2 *select, char *sense, int *n, d *a, int *lda, int *sdim, d *wr, d *wi, d *vs, int *ldvs, d *rconde, d *rcondv, d *work, int *lwork, int *iwork, int *liwork, bint *bwork, int *info)
  74. void dgges(char *jobvsl, char *jobvsr, char *sort, dselect3 *selctg, int *n, d *a, int *lda, d *b, int *ldb, int *sdim, d *alphar, d *alphai, d *beta, d *vsl, int *ldvsl, d *vsr, int *ldvsr, d *work, int *lwork, bint *bwork, int *info)
  75. void dggesx(char *jobvsl, char *jobvsr, char *sort, dselect3 *selctg, char *sense, int *n, d *a, int *lda, d *b, int *ldb, int *sdim, d *alphar, d *alphai, d *beta, d *vsl, int *ldvsl, d *vsr, int *ldvsr, d *rconde, d *rcondv, d *work, int *lwork, int *iwork, int *liwork, bint *bwork, int *info)
  76. d dlamch(char *cmach)
  77. void ilaver(int *vers_major, int *vers_minor, int *vers_patch)
  78. void sgees(char *jobvs, char *sort, sselect2 *select, int *n, s *a, int *lda, int *sdim, s *wr, s *wi, s *vs, int *ldvs, s *work, int *lwork, bint *bwork, int *info)
  79. void sgeesx(char *jobvs, char *sort, sselect2 *select, char *sense, int *n, s *a, int *lda, int *sdim, s *wr, s *wi, s *vs, int *ldvs, s *rconde, s *rcondv, s *work, int *lwork, int *iwork, int *liwork, bint *bwork, int *info)
  80. void sgges(char *jobvsl, char *jobvsr, char *sort, sselect3 *selctg, int *n, s *a, int *lda, s *b, int *ldb, int *sdim, s *alphar, s *alphai, s *beta, s *vsl, int *ldvsl, s *vsr, int *ldvsr, s *work, int *lwork, bint *bwork, int *info)
  81. void sggesx(char *jobvsl, char *jobvsr, char *sort, sselect3 *selctg, char *sense, int *n, s *a, int *lda, s *b, int *ldb, int *sdim, s *alphar, s *alphai, s *beta, s *vsl, int *ldvsl, s *vsr, int *ldvsr, s *rconde, s *rcondv, s *work, int *lwork, int *iwork, int *liwork, bint *bwork, int *info)
  82. s slamch(char *cmach)
  83. void zgees(char *jobvs, char *sort, zselect1 *select, int *n, z *a, int *lda, int *sdim, z *w, z *vs, int *ldvs, z *work, int *lwork, d *rwork, bint *bwork, int *info)
  84. void zgeesx(char *jobvs, char *sort, zselect1 *select, char *sense, int *n, z *a, int *lda, int *sdim, z *w, z *vs, int *ldvs, d *rconde, d *rcondv, z *work, int *lwork, d *rwork, bint *bwork, int *info)
  85. void zgges(char *jobvsl, char *jobvsr, char *sort, zselect2 *selctg, int *n, z *a, int *lda, z *b, int *ldb, int *sdim, z *alpha, z *beta, z *vsl, int *ldvsl, z *vsr, int *ldvsr, z *work, int *lwork, d *rwork, bint *bwork, int *info)
  86. void zggesx(char *jobvsl, char *jobvsr, char *sort, zselect2 *selctg, char *sense, int *n, z *a, int *lda, z *b, int *ldb, int *sdim, z *alpha, z *beta, z *vsl, int *ldvsl, z *vsr, int *ldvsr, d *rconde, d *rcondv, z *work, int *lwork, d *rwork, int *iwork, int *liwork, bint *bwork, int *info)'''
  87. if __name__ == '__main__':
  88. from sys import argv
  89. libname, src_dir, outfile = argv[1:]
  90. # Exclude scabs and sisnan since they aren't currently included
  91. # in the scipy-specific ABI wrappers.
  92. if libname.lower() == 'blas':
  93. sigs_from_dir(src_dir, outfile, exclusions=['scabs1', 'xerbla'])
  94. elif libname.lower() == 'lapack':
  95. # Exclude all routines that do not have consistent interfaces from
  96. # LAPACK 3.4.0 through 3.6.0.
  97. # Also exclude routines with string arguments to avoid
  98. # compatibility woes with different standards for string arguments.
  99. exclusions = [
  100. # Not included because people should be using the
  101. # C standard library function instead.
  102. # sisnan is also not currently included in the
  103. # ABI wrappers.
  104. 'sisnan', 'dlaisnan', 'slaisnan',
  105. # Exclude slaneg because it isn't currently included
  106. # in the ABI wrappers
  107. 'slaneg',
  108. # Excluded because they require Fortran string arguments.
  109. 'ilaenv', 'iparmq', 'lsamen', 'xerbla',
  110. # Exclude XBLAS routines since they aren't included
  111. # by default.
  112. 'cgesvxx', 'dgesvxx', 'sgesvxx', 'zgesvxx',
  113. 'cgerfsx', 'dgerfsx', 'sgerfsx', 'zgerfsx',
  114. 'cla_gerfsx_extended', 'dla_gerfsx_extended',
  115. 'sla_gerfsx_extended', 'zla_gerfsx_extended',
  116. 'cla_geamv', 'dla_geamv', 'sla_geamv', 'zla_geamv',
  117. 'dla_gercond', 'sla_gercond',
  118. 'cla_gercond_c', 'zla_gercond_c',
  119. 'cla_gercond_x', 'zla_gercond_x',
  120. 'cla_gerpvgrw', 'dla_gerpvgrw',
  121. 'sla_gerpvgrw', 'zla_gerpvgrw',
  122. 'csysvxx', 'dsysvxx', 'ssysvxx', 'zsysvxx',
  123. 'csyrfsx', 'dsyrfsx', 'ssyrfsx', 'zsyrfsx',
  124. 'cla_syrfsx_extended', 'dla_syrfsx_extended',
  125. 'sla_syrfsx_extended', 'zla_syrfsx_extended',
  126. 'cla_syamv', 'dla_syamv', 'sla_syamv', 'zla_syamv',
  127. 'dla_syrcond', 'sla_syrcond',
  128. 'cla_syrcond_c', 'zla_syrcond_c',
  129. 'cla_syrcond_x', 'zla_syrcond_x',
  130. 'cla_syrpvgrw', 'dla_syrpvgrw',
  131. 'sla_syrpvgrw', 'zla_syrpvgrw',
  132. 'cposvxx', 'dposvxx', 'sposvxx', 'zposvxx',
  133. 'cporfsx', 'dporfsx', 'sporfsx', 'zporfsx',
  134. 'cla_porfsx_extended', 'dla_porfsx_extended',
  135. 'sla_porfsx_extended', 'zla_porfsx_extended',
  136. 'dla_porcond', 'sla_porcond',
  137. 'cla_porcond_c', 'zla_porcond_c',
  138. 'cla_porcond_x', 'zla_porcond_x',
  139. 'cla_porpvgrw', 'dla_porpvgrw',
  140. 'sla_porpvgrw', 'zla_porpvgrw',
  141. 'cgbsvxx', 'dgbsvxx', 'sgbsvxx', 'zgbsvxx',
  142. 'cgbrfsx', 'dgbrfsx', 'sgbrfsx', 'zgbrfsx',
  143. 'cla_gbrfsx_extended', 'dla_gbrfsx_extended',
  144. 'sla_gbrfsx_extended', 'zla_gbrfsx_extended',
  145. 'cla_gbamv', 'dla_gbamv', 'sla_gbamv', 'zla_gbamv',
  146. 'dla_gbrcond', 'sla_gbrcond',
  147. 'cla_gbrcond_c', 'zla_gbrcond_c',
  148. 'cla_gbrcond_x', 'zla_gbrcond_x',
  149. 'cla_gbrpvgrw', 'dla_gbrpvgrw',
  150. 'sla_gbrpvgrw', 'zla_gbrpvgrw',
  151. 'chesvxx', 'zhesvxx',
  152. 'cherfsx', 'zherfsx',
  153. 'cla_herfsx_extended', 'zla_herfsx_extended',
  154. 'cla_heamv', 'zla_heamv',
  155. 'cla_hercond_c', 'zla_hercond_c',
  156. 'cla_hercond_x', 'zla_hercond_x',
  157. 'cla_herpvgrw', 'zla_herpvgrw',
  158. 'sla_lin_berr', 'cla_lin_berr',
  159. 'dla_lin_berr', 'zla_lin_berr',
  160. 'clarscl2', 'dlarscl2', 'slarscl2', 'zlarscl2',
  161. 'clascl2', 'dlascl2', 'slascl2', 'zlascl2',
  162. 'cla_wwaddw', 'dla_wwaddw', 'sla_wwaddw', 'zla_wwaddw',
  163. # Removed between 3.3.1 and 3.4.0.
  164. 'cla_rpvgrw', 'dla_rpvgrw', 'sla_rpvgrw', 'zla_rpvgrw',
  165. # Signatures changed between 3.4.0 and 3.4.1.
  166. 'dlasq5', 'slasq5',
  167. # Routines deprecated in LAPACK 3.6.0
  168. 'cgegs', 'cgegv', 'cgelsx',
  169. 'cgeqpf', 'cggsvd', 'cggsvp',
  170. 'clahrd', 'clatzm', 'ctzrqf',
  171. 'dgegs', 'dgegv', 'dgelsx',
  172. 'dgeqpf', 'dggsvd', 'dggsvp',
  173. 'dlahrd', 'dlatzm', 'dtzrqf',
  174. 'sgegs', 'sgegv', 'sgelsx',
  175. 'sgeqpf', 'sggsvd', 'sggsvp',
  176. 'slahrd', 'slatzm', 'stzrqf',
  177. 'zgegs', 'zgegv', 'zgelsx',
  178. 'zgeqpf', 'zggsvd', 'zggsvp',
  179. 'zlahrd', 'zlatzm', 'ztzrqf']
  180. sigs_from_dir(src_dir, outfile, manual_wrappers=lapack_manual_wrappers,
  181. exclusions=exclusions)