-
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from defeo/autogen_decl
Autogeneration of pari declarations
- Loading branch information
Showing
8 changed files
with
102 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
|
||
#***************************************************************************** | ||
# Copyright (C) 2015 Jeroen Demeyer <[email protected]> | ||
# 2017 Vincent Delecroix <[email protected]> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
|
@@ -16,7 +17,7 @@ | |
import os, re, sys | ||
|
||
from .args import PariArgumentGEN, PariInstanceArgument | ||
from .parser import (read_pari_desc, read_decl, parse_prototype) | ||
from .parser import read_pari_desc, parse_prototype | ||
from .doc import get_rest_doc | ||
|
||
|
||
|
@@ -42,12 +43,52 @@ | |
""" | ||
'''.format(__file__) | ||
|
||
decl_banner='''# This file is auto-generated by {} | ||
from .types cimport * | ||
cdef extern from *: | ||
'''.format(__file__) | ||
|
||
|
||
function_re = re.compile(r"^[A-Za-z][A-Za-z0-9_]*$") | ||
function_blacklist = {"O", # O(p^e) needs special parser support | ||
"alias", # Not needed and difficult documentation | ||
"listcreate", # "redundant and obsolete" according to PARI | ||
"allocatemem", # Better hand-written support in Pari class | ||
"global", # Invalid in Python (and obsolete) | ||
"inline", # Total confusion | ||
"uninline", # idem | ||
"local", # idem | ||
"my", # idem | ||
"plot", # Graphical function undeclared in pari public headers | ||
"plotbox", # idem | ||
"plotclip", # idem | ||
"plotcursor", # idem | ||
"plotcolor", # idem | ||
"plotcopy", # idem | ||
"plotdraw", # idem | ||
"plothsizes", # idem | ||
"plotinit", # idem | ||
"plotkill", # idem | ||
"plotlines", # idem | ||
"plotlinetype", # idem | ||
"plotmove", # idem | ||
"plotpoints", # idem | ||
"plotpointsize", # idem | ||
"plotpointtype", # idem | ||
"plotrbox", # idem | ||
"plotrecth", # idem | ||
"plotrecthraw", # idem | ||
"plotrline", # idem | ||
"plotrmove", # idem | ||
"plotrpoint", # idem | ||
"plotscale", # idem | ||
"plotstring", # idem | ||
"ploth", # idem | ||
"plothraw", # idem | ||
"psdraw", # idem | ||
"psplothraw", # idem | ||
} | ||
|
||
class PariFunctionGenerator(object): | ||
|
@@ -59,9 +100,9 @@ class PariFunctionGenerator(object): | |
:class:`Pari`. | ||
""" | ||
def __init__(self): | ||
self.declared = read_decl() | ||
self.gen_filename = os.path.join('cypari2', 'auto_gen.pxi') | ||
self.instance_filename = os.path.join('cypari2', 'auto_instance.pxi') | ||
self.decl_filename = os.path.join('cypari2', 'auto_paridecl.pxd') | ||
|
||
def can_handle_function(self, function, cname="", **kwds): | ||
""" | ||
|
@@ -75,8 +116,6 @@ def can_handle_function(self, function, cname="", **kwds): | |
True | ||
>>> G.can_handle_function("_bnfinit", "bnfinit0", **{"class":"basic"}) | ||
False | ||
>>> G.can_handle_function("bnfinit", "BNFINIT0", **{"class":"basic"}) | ||
False | ||
>>> G.can_handle_function("bnfinit", "bnfinit0", **{"class":"hard"}) | ||
False | ||
""" | ||
|
@@ -86,9 +125,6 @@ def can_handle_function(self, function, cname="", **kwds): | |
if not function_re.match(function): | ||
# Not a legal function name, like "!_" | ||
return False | ||
if cname not in self.declared: | ||
# PARI function not in paridecl.pxd or declinl.pxi | ||
return False | ||
cls = kwds.get("class", "unknown") | ||
sec = kwds.get("section", "unknown") | ||
if cls not in ("basic", "highlevel"): | ||
|
@@ -100,7 +136,7 @@ def can_handle_function(self, function, cname="", **kwds): | |
return False | ||
return True | ||
|
||
def handle_pari_function(self, function, cname="", prototype="", help="", obsolete=None, **kwds): | ||
def handle_pari_function(self, function, cname, prototype="", help="", obsolete=None, **kwds): | ||
r""" | ||
Handle one PARI function: decide whether or not to add the | ||
function, in which file (as method of :class:`Gen` or | ||
|
@@ -114,10 +150,12 @@ def handle_pari_function(self, function, cname="", prototype="", help="", obsole | |
>>> G = PariFunctionGenerator() | ||
>>> G.gen_file = sys.stdout | ||
>>> G.instance_file = sys.stdout | ||
>>> G.decl_file = sys.stdout | ||
>>> G.handle_pari_function("bnfinit", | ||
... cname="bnfinit0", prototype="GD0,L,DGp", | ||
... help=r"bnfinit(P,{flag=0},{tech=[]}): compute...", | ||
... **{"class":"basic", "section":"number_fields"}) | ||
GEN bnfinit0(GEN, long, GEN, long) | ||
def bnfinit(P, long flag=0, tech=None, long precision=0): | ||
... | ||
cdef GEN _P = P.g | ||
|
@@ -135,6 +173,7 @@ def bnfinit(P, long flag=0, tech=None, long precision=0): | |
... cname="ellmodulareqn", prototype="LDnDn", | ||
... help=r"ellmodulareqn(N,{x},{y}): return...", | ||
... **{"class":"basic", "section":"elliptic_curves"}) | ||
GEN ellmodulareqn(long, long, long) | ||
def ellmodulareqn(self, long N, x=None, y=None): | ||
... | ||
cdef long _x = -1 | ||
|
@@ -152,6 +191,7 @@ def ellmodulareqn(self, long N, x=None, y=None): | |
... help=r"setrand(n): reset the seed...", | ||
... doc=r"reseeds the random number generator...", | ||
... **{"class":"basic", "section":"programming/specific"}) | ||
void setrand(GEN) | ||
def setrand(n): | ||
r''' | ||
Reseeds the random number generator using the seed :math:`n`. No value is | ||
|
@@ -171,6 +211,7 @@ def setrand(n): | |
... help="bernvec(x): this routine is obsolete, use bernfrac repeatedly.", | ||
... obsolete="2007-03-30", | ||
... **{"class":"basic", "section":"transcendental"}) | ||
GEN bernvec(long) | ||
def bernvec(self, long x): | ||
r''' | ||
This routine is obsolete, kept for backward compatibility only. | ||
|
@@ -189,6 +230,8 @@ def bernvec(self, long x): | |
|
||
doc = get_rest_doc(function) | ||
|
||
self.write_declaration(cname, args, ret, self.decl_file) | ||
|
||
if len(args) > 0 and isinstance(args[0], PariArgumentGEN): | ||
# If the first argument is a GEN, write a method of the | ||
# Gen class. | ||
|
@@ -201,6 +244,23 @@ def bernvec(self, long x): | |
self.write_method(function, cname, args, ret, args[1:], | ||
self.instance_file, doc, obsolete) | ||
|
||
def write_declaration(self, cname, args, ret, file): | ||
""" | ||
Write a .pxd declaration of a PARI library function. | ||
INPUT: | ||
- ``cname`` -- name of the PARI C library call | ||
- ``args``, ``ret`` -- output from ``parse_prototype`` | ||
- ``file`` -- a file object where the declaration should be | ||
written to | ||
""" | ||
args = ", ".join(a.ctype() for a in args) | ||
s = ' {ret} {function}({args})'.format(ret=ret.ctype(), function=cname, args=args) | ||
print(s, file=file) | ||
|
||
def write_method(self, function, cname, args, ret, cargs, file, doc, obsolete): | ||
""" | ||
Write Cython code with a method to call one PARI function. | ||
|
@@ -264,6 +324,8 @@ def __call__(self): | |
self.gen_file.write(gen_banner) | ||
self.instance_file = open(self.instance_filename + '.tmp', 'w') | ||
self.instance_file.write(instance_banner) | ||
self.decl_file = open(self.decl_filename + '.tmp', 'w') | ||
self.decl_file.write(decl_banner) | ||
|
||
for v in D: | ||
if not self.can_handle_function(**v): | ||
|
@@ -276,7 +338,9 @@ def __call__(self): | |
|
||
self.gen_file.close() | ||
self.instance_file.close() | ||
self.decl_file.close() | ||
|
||
# All done? Let's commit. | ||
os.rename(self.gen_filename + '.tmp', self.gen_filename) | ||
os.rename(self.instance_filename + '.tmp', self.instance_filename) | ||
os.rename(self.decl_filename + '.tmp', self.decl_filename) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters