Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sage
Path: blob/develop/src/sage_setup/autogen/flint/writer.py
4086 views
1
r"""
2
Write flint header files.
3
"""
4
#*****************************************************************************
5
# Copyright (C) 2023 Vincent Delecroix <[email protected]>
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 2 of the License, or
10
# (at your option) any later version.
11
# http://www.gnu.org/licenses/
12
#*****************************************************************************
13
14
import os
15
import shutil
16
from .env import AUTOGEN_DIR, FLINT_GIT_DIR, FLINT_DOC_DIR, FLINT_INCLUDE_DIR
17
from .reader import extract_functions
18
19
20
def write_flint_cython_headers(output_dir, documentation=False):
21
r"""
22
Write cython header files.
23
24
Arguments
25
output_dir -- (string) path where to write the .pxd files
26
27
Requires gitpython to be installed.
28
"""
29
if not os.path.isdir(os.path.join(FLINT_GIT_DIR, ".git")):
30
raise ValueError(f"FLINT_GIT_DIR(={FLINT_GIT_DIR}) is not a Git repository")
31
32
import git
33
repo = git.Repo(FLINT_GIT_DIR)
34
commit = repo.head.commit
35
print(f"Generating cython headers from {commit}")
36
37
header_list = []
38
pxd_list = []
39
for filename in os.listdir(FLINT_DOC_DIR):
40
if not filename.endswith('.rst'):
41
continue
42
prefix = filename[:-4]
43
44
absolute_filename = os.path.join(FLINT_DOC_DIR, filename)
45
content = extract_functions(absolute_filename)
46
if not content:
47
# NOTE: skip files with no function declaration
48
continue
49
50
# try to match header
51
header = prefix + '.h'
52
if prefix == 'flint':
53
header = header + '.in'
54
absolute_header = os.path.join(FLINT_INCLUDE_DIR, header)
55
56
if not os.path.isfile(absolute_header):
57
print('Warning: skipping {} because no associated .h found'.format(filename))
58
continue
59
60
# TODO: below are some exceptions for which we do not create .pxd file
61
if prefix == 'machine_vectors' or prefix == 'fft_small':
62
print('Warning: ignoring machine_vectors and fft_small because architecture dependent')
63
continue
64
if prefix == 'acb_theta':
65
print('Warning: ignoring acb_theta because not in stable release')
66
continue
67
68
header_list.append(prefix + '.h')
69
pxd_list.append(prefix + '.pxd')
70
71
output = open(os.path.join(output_dir, prefix + '.pxd'), 'w')
72
73
print('# distutils: libraries = flint', file=output)
74
print('# distutils: depends = flint/{}'.format(prefix + '.h'), file=output)
75
print(file=output)
76
print('#' * 80, file=output)
77
print('# This file is auto-generated by the script', file=output)
78
print('# SAGE_ROOT/src/sage_setup/autogen/flint_autogen.py.', file=output)
79
print('# From the commit {}'.format(commit), file=output)
80
print('# Do not modify by hand! Fix and rerun the script instead.', file=output)
81
print('#' * 80, file=output)
82
print(file=output)
83
84
print('from libc.stdio cimport FILE', file=output)
85
print('from sage.libs.gmp.types cimport *', file=output)
86
print('from sage.libs.mpfr.types cimport *', file=output)
87
print('from sage.libs.flint.types cimport *', file=output)
88
print(file=output)
89
90
print('cdef extern from "flint_wrap.h":', file=output)
91
92
for section in content:
93
if section is not None:
94
print(' ## {}'.format(section), file=output)
95
for func_signatures, doc in content[section]:
96
if documentation:
97
print(file=output)
98
for line in doc:
99
print(' # {}'.format(line), file=output)
100
for line in func_signatures:
101
print(' {} noexcept'.format(line), file=output)
102
103
if os.path.isfile(os.path.join(AUTOGEN_DIR, 'macros', prefix + '_macros.pxd')):
104
print('\nfrom .{} cimport *'.format(prefix + '_macros'), file=output)
105
106
output.close()
107
108
for extra_header in ['nmod_types.h']:
109
if extra_header in header_list:
110
print('Warning: {} already in HEADER_LIST'.format(extra_header))
111
header_list.append(extra_header)
112
113
header_list.sort()
114
pxd_list.sort()
115
116
with open(os.path.join(AUTOGEN_DIR, 'templates', 'flint_wrap.h.template')) as f:
117
text = f.read()
118
with open(os.path.join(output_dir, 'flint_wrap.h'), 'w') as output:
119
output.write(text.format(HEADER_LIST='\n'.join('#include <flint/{}>'.format(header) for header in header_list)))
120
121
with open(os.path.join(AUTOGEN_DIR, 'templates', 'types.pxd.template')) as f:
122
text = f.read()
123
with open(os.path.join(output_dir, 'types.pxd'), 'w') as output:
124
output.write(text.format(HEADER_LIST=' '.join('flint/{}'.format(header) for header in header_list)))
125
126
for filename in os.listdir(os.path.join(AUTOGEN_DIR, 'macros')):
127
prefix = filename[:-4]
128
shutil.copy(os.path.join(AUTOGEN_DIR, 'macros', filename), os.path.join(output_dir, filename))
129
130
with open(os.path.join(AUTOGEN_DIR, 'templates', 'flint_sage.pyx.template')) as f:
131
text = f.read()
132
with open(os.path.join(output_dir, 'flint_sage.pyx'), 'w') as output:
133
output.write(text.format(CYTHON_IMPORTS='\n'.join('from .{} cimport *'.format(header[:-4]) for header in pxd_list)))
134
135