4
4
5
5
#*****************************************************************************
6
6
# Copyright (C) 2015 Jeroen Demeyer <[email protected] >
7
+ # 2017 Vincent Delecroix <[email protected] >
7
8
#
8
9
# This program is free software: you can redistribute it and/or modify
9
10
# it under the terms of the GNU General Public License as published by
16
17
import os , re , sys
17
18
18
19
from .args import PariArgumentGEN , PariInstanceArgument
19
- from .parser import ( read_pari_desc , read_decl , parse_prototype )
20
+ from .parser import read_pari_desc , parse_prototype
20
21
from .doc import get_rest_doc
21
22
22
23
42
43
"""
43
44
''' .format (__file__ )
44
45
46
+ decl_banner = '''# This file is auto-generated by {}
47
+
48
+ from .types cimport *
49
+
50
+ cdef extern from *:
51
+ ''' .format (__file__ )
52
+
45
53
46
54
function_re = re .compile (r"^[A-Za-z][A-Za-z0-9_]*$" )
47
55
function_blacklist = {"O" , # O(p^e) needs special parser support
48
56
"alias" , # Not needed and difficult documentation
49
57
"listcreate" , # "redundant and obsolete" according to PARI
50
58
"allocatemem" , # Better hand-written support in Pari class
59
+ "global" , # Invalid in Python (and obsolete)
60
+ "inline" , # Total confusion
61
+ "uninline" , # idem
62
+ "local" , # idem
63
+ "my" , # idem
64
+ "plot" , # Graphical function undeclared in pari public headers
65
+ "plotbox" , # idem
66
+ "plotclip" , # idem
67
+ "plotcursor" , # idem
68
+ "plotcolor" , # idem
69
+ "plotcopy" , # idem
70
+ "plotdraw" , # idem
71
+ "plothsizes" , # idem
72
+ "plotinit" , # idem
73
+ "plotkill" , # idem
74
+ "plotlines" , # idem
75
+ "plotlinetype" , # idem
76
+ "plotmove" , # idem
77
+ "plotpoints" , # idem
78
+ "plotpointsize" , # idem
79
+ "plotpointtype" , # idem
80
+ "plotrbox" , # idem
81
+ "plotrecth" , # idem
82
+ "plotrecthraw" , # idem
83
+ "plotrline" , # idem
84
+ "plotrmove" , # idem
85
+ "plotrpoint" , # idem
86
+ "plotscale" , # idem
87
+ "plotstring" , # idem
88
+ "ploth" , # idem
89
+ "plothraw" , # idem
90
+ "psdraw" , # idem
91
+ "psplothraw" , # idem
51
92
}
52
93
53
94
class PariFunctionGenerator (object ):
@@ -59,9 +100,9 @@ class PariFunctionGenerator(object):
59
100
:class:`Pari`.
60
101
"""
61
102
def __init__ (self ):
62
- self .declared = read_decl ()
63
103
self .gen_filename = os .path .join ('cypari2' , 'auto_gen.pxi' )
64
104
self .instance_filename = os .path .join ('cypari2' , 'auto_instance.pxi' )
105
+ self .decl_filename = os .path .join ('cypari2' , 'auto_paridecl.pxd' )
65
106
66
107
def can_handle_function (self , function , cname = "" , ** kwds ):
67
108
"""
@@ -75,8 +116,6 @@ def can_handle_function(self, function, cname="", **kwds):
75
116
True
76
117
>>> G.can_handle_function("_bnfinit", "bnfinit0", **{"class":"basic"})
77
118
False
78
- >>> G.can_handle_function("bnfinit", "BNFINIT0", **{"class":"basic"})
79
- False
80
119
>>> G.can_handle_function("bnfinit", "bnfinit0", **{"class":"hard"})
81
120
False
82
121
"""
@@ -86,9 +125,6 @@ def can_handle_function(self, function, cname="", **kwds):
86
125
if not function_re .match (function ):
87
126
# Not a legal function name, like "!_"
88
127
return False
89
- if cname not in self .declared :
90
- # PARI function not in paridecl.pxd or declinl.pxi
91
- return False
92
128
cls = kwds .get ("class" , "unknown" )
93
129
sec = kwds .get ("section" , "unknown" )
94
130
if cls not in ("basic" , "highlevel" ):
@@ -100,7 +136,7 @@ def can_handle_function(self, function, cname="", **kwds):
100
136
return False
101
137
return True
102
138
103
- def handle_pari_function (self , function , cname = "" , prototype = "" , help = "" , obsolete = None , ** kwds ):
139
+ def handle_pari_function (self , function , cname , prototype = "" , help = "" , obsolete = None , ** kwds ):
104
140
r"""
105
141
Handle one PARI function: decide whether or not to add the
106
142
function, in which file (as method of :class:`Gen` or
@@ -114,10 +150,12 @@ def handle_pari_function(self, function, cname="", prototype="", help="", obsole
114
150
>>> G = PariFunctionGenerator()
115
151
>>> G.gen_file = sys.stdout
116
152
>>> G.instance_file = sys.stdout
153
+ >>> G.decl_file = sys.stdout
117
154
>>> G.handle_pari_function("bnfinit",
118
155
... cname="bnfinit0", prototype="GD0,L,DGp",
119
156
... help=r"bnfinit(P,{flag=0},{tech=[]}): compute...",
120
157
... **{"class":"basic", "section":"number_fields"})
158
+ GEN bnfinit0(GEN, long, GEN, long)
121
159
def bnfinit(P, long flag=0, tech=None, long precision=0):
122
160
...
123
161
cdef GEN _P = P.g
@@ -135,6 +173,7 @@ def bnfinit(P, long flag=0, tech=None, long precision=0):
135
173
... cname="ellmodulareqn", prototype="LDnDn",
136
174
... help=r"ellmodulareqn(N,{x},{y}): return...",
137
175
... **{"class":"basic", "section":"elliptic_curves"})
176
+ GEN ellmodulareqn(long, long, long)
138
177
def ellmodulareqn(self, long N, x=None, y=None):
139
178
...
140
179
cdef long _x = -1
@@ -152,6 +191,7 @@ def ellmodulareqn(self, long N, x=None, y=None):
152
191
... help=r"setrand(n): reset the seed...",
153
192
... doc=r"reseeds the random number generator...",
154
193
... **{"class":"basic", "section":"programming/specific"})
194
+ void setrand(GEN)
155
195
def setrand(n):
156
196
r'''
157
197
Reseeds the random number generator using the seed :math:`n`. No value is
@@ -171,6 +211,7 @@ def setrand(n):
171
211
... help="bernvec(x): this routine is obsolete, use bernfrac repeatedly.",
172
212
... obsolete="2007-03-30",
173
213
... **{"class":"basic", "section":"transcendental"})
214
+ GEN bernvec(long)
174
215
def bernvec(self, long x):
175
216
r'''
176
217
This routine is obsolete, kept for backward compatibility only.
@@ -189,6 +230,8 @@ def bernvec(self, long x):
189
230
190
231
doc = get_rest_doc (function )
191
232
233
+ self .write_declaration (cname , args , ret , self .decl_file )
234
+
192
235
if len (args ) > 0 and isinstance (args [0 ], PariArgumentGEN ):
193
236
# If the first argument is a GEN, write a method of the
194
237
# Gen class.
@@ -201,6 +244,23 @@ def bernvec(self, long x):
201
244
self .write_method (function , cname , args , ret , args [1 :],
202
245
self .instance_file , doc , obsolete )
203
246
247
+ def write_declaration (self , cname , args , ret , file ):
248
+ """
249
+ Write a .pxd declaration of a PARI library function.
250
+
251
+ INPUT:
252
+
253
+ - ``cname`` -- name of the PARI C library call
254
+
255
+ - ``args``, ``ret`` -- output from ``parse_prototype``
256
+
257
+ - ``file`` -- a file object where the declaration should be
258
+ written to
259
+ """
260
+ args = ", " .join (a .ctype () for a in args )
261
+ s = ' {ret} {function}({args})' .format (ret = ret .ctype (), function = cname , args = args )
262
+ print (s , file = file )
263
+
204
264
def write_method (self , function , cname , args , ret , cargs , file , doc , obsolete ):
205
265
"""
206
266
Write Cython code with a method to call one PARI function.
@@ -264,6 +324,8 @@ def __call__(self):
264
324
self .gen_file .write (gen_banner )
265
325
self .instance_file = open (self .instance_filename + '.tmp' , 'w' )
266
326
self .instance_file .write (instance_banner )
327
+ self .decl_file = open (self .decl_filename + '.tmp' , 'w' )
328
+ self .decl_file .write (decl_banner )
267
329
268
330
for v in D :
269
331
if not self .can_handle_function (** v ):
@@ -276,7 +338,9 @@ def __call__(self):
276
338
277
339
self .gen_file .close ()
278
340
self .instance_file .close ()
341
+ self .decl_file .close ()
279
342
280
343
# All done? Let's commit.
281
344
os .rename (self .gen_filename + '.tmp' , self .gen_filename )
282
345
os .rename (self .instance_filename + '.tmp' , self .instance_filename )
346
+ os .rename (self .decl_filename + '.tmp' , self .decl_filename )
0 commit comments