Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/misc/inline_fortran.py
4045 views
1
import __builtin__
2
import os
3
4
from sage.misc.misc import tmp_filename
5
6
count=0
7
8
9
class InlineFortran:
10
def __init__(self,globals):
11
self.globals=globals
12
self.library_paths=[]
13
self.libraries=[]
14
self.verbose = False
15
16
def __repr__(self):
17
return "Interface to Fortran compiler"
18
19
def __call__(self, *args, **kwds):
20
return self.eval(*args, **kwds)
21
22
def eval(self,x,globals=None, locals=None):
23
"""
24
EXAMPLES::
25
26
sage: from sage.misc.inline_fortran import InlineFortran, _example
27
sage: test_fortran = InlineFortran(globals()) # optional -- fortran
28
sage: test_fortran(_example) # optional -- fortran
29
sage: import numpy
30
sage: n = numpy.array(range(10),dtype=float)
31
sage: fib(n,int(10)) # optional -- fortran
32
sage: n # optional -- fortran
33
array([ 0., 1., 1., 2., 3., 5., 8., 13., 21., 34.])
34
"""
35
if len(x.splitlines()) == 1 and os.path.exists(x):
36
filename = x
37
x = open(x).read()
38
if filename.lower().endswith('.f90'):
39
x = '!f90\n' + x
40
global count
41
# On linux g77_shared should be a script that runs sage_fortran -shared
42
# On OS X it should be a script that runs gfortran -bundle -undefined dynamic_lookup
43
path = os.environ['SAGE_LOCAL']+'/bin/sage-g77_shared'
44
from numpy import f2py
45
old_import_path=os.sys.path
46
cwd=os.getcwd()
47
os.sys.path.append(cwd)
48
49
#name = tmp_dir() + '/fortran_module_%d'%count
50
name = 'fortran_module_%d'%count
51
if os.path.exists(name):
52
os.unlink(name)
53
s_lib_path=""
54
s_lib=""
55
for s in self.library_paths:
56
s_lib_path=s_lib_path+"-L"+s+" "
57
58
for s in self.libraries:
59
s_lib=s_lib +"-l"+s + " "
60
61
# if the first line has !f90 as a comment gfortran will treat it as
62
# fortran 90 code
63
if x.startswith('!f90'):
64
fname = os.path.join(tmp_filename() +'.f90')
65
else:
66
fname = os.path.join(tmp_filename() +'.f')
67
68
log = tmp_filename()
69
extra_args = '--quiet --f77exec=%s --f90exec=%s %s %s 1>&2 >"%s"'%(
70
path, path, s_lib_path, s_lib, log)
71
72
f2py.compile(x, name, extra_args = extra_args, source_fn=fname)
73
74
log_string = open(log).read()
75
76
os.unlink(log)
77
os.unlink(fname)
78
79
if self.verbose:
80
print log_string
81
82
count += 1
83
try:
84
m=__builtin__.__import__(name)
85
except ImportError:
86
if not self.verbose:
87
print log_string
88
return
89
finally:
90
os.sys.path=old_import_path
91
os.unlink(name + '.so')
92
93
for k, x in m.__dict__.iteritems():
94
if k[0] != '_':
95
self.globals[k] = x
96
97
def add_library(self,s):
98
self.libraries.append(s)
99
100
def add_library_path(self,s):
101
self.library_paths.append(s)
102
103
104
_example = """
105
C FILE: FIB1.F
106
SUBROUTINE FIB(A,N)
107
C
108
C CALCULATE FIRST N FIBONACCI NUMBERS
109
C
110
INTEGER N
111
REAL*8 A(N)
112
DO I=1,N
113
IF (I.EQ.1) THEN
114
A(I) = 0.0D0
115
ELSEIF (I.EQ.2) THEN
116
A(I) = 1.0D0
117
ELSE
118
A(I) = A(I-1) + A(I-2)
119
ENDIF
120
ENDDO
121
END
122
C END FILE FIB1.F
123
"""
124
125