6
6
import copy
7
7
8
8
# Create linear algebra constants module
9
- def create_constants_module (module_name ,out_folder ):
9
+ def create_constants_module (module_name ,out_folder , stdlib_integration = None ):
10
10
11
11
from platform import os
12
12
@@ -23,20 +23,30 @@ def create_constants_module(module_name,out_folder):
23
23
24
24
# Header
25
25
fid .write ("module {}\n " .format (module_name ))
26
- #fid.write(INDENT + "use stdlib_kinds, only: sp,dp,lk,int32,int64\n")
27
- fid .write (INDENT + "use iso_fortran_env, only: int32,int64\n " )
26
+
27
+ if stdlib_integration :
28
+ fid .write (INDENT + "use stdlib_kinds, only: sp, dp, qp, int32, int64, lk\n " )
29
+ else :
30
+ fid .write (INDENT + "use iso_fortran_env, only: real32,real64,real128,int32,int64\n " )
31
+
28
32
fid .write (INDENT + "use, intrinsic :: ieee_arithmetic, only: ieee_is_nan \n " )
29
33
fid .write ("#if defined(_OPENMP)\n " )
30
34
fid .write (INDENT + "use omp_lib\n " )
31
35
fid .write ("#endif\n " )
32
36
fid .write (INDENT + "implicit none(type,external)\n " )
33
37
fid .write (INDENT + "public\n \n \n \n " )
34
38
39
+ #:if WITH_QP
40
+ #:set REAL_KINDS = REAL_KINDS + ["qp"]
41
+ #:endif
42
+
35
43
# Temporary: to be replaced with stdlib_kinds
36
- fid .write (INDENT + "integer, parameter :: sp = selected_real_kind(6)\n " )
37
- fid .write (INDENT + "integer, parameter :: dp = selected_real_kind(15)\n " )
38
- fid .write (INDENT + "integer, parameter :: qp = selected_real_kind(33)\n " )
39
- fid .write (INDENT + "integer, parameter :: lk = kind(.true.)\n " )
44
+ if not stdlib_integration :
45
+ fid .write (INDENT + "integer, parameter :: sp = real32\n " )
46
+ fid .write (INDENT + "integer, parameter :: dp = real64\n " )
47
+ fid .write (INDENT + "integer, parameter :: qp = real128\n " )
48
+ fid .write (INDENT + "integer, parameter :: lk = kind(.true.)\n " )
49
+
40
50
fid .write (INDENT + "! Integer size support for ILP64 builds should be done here\n " )
41
51
fid .write (INDENT + "integer, parameter :: ilp = int32\n " )
42
52
fid .write (INDENT + "private :: int32, int64\n \n \n " )
@@ -99,7 +109,7 @@ def patch_lapack_aux(fid,prefix,indent):
99
109
# Read all source files from the source folder, process them, refactor them, and put all
100
110
# subroutines/function into a module
101
111
def create_fortran_module (module_name ,source_folder ,out_folder ,prefix ,ext_functions ,used_modules , \
102
- split_by_initial ):
112
+ split_by_initial , stdlib_export = False ):
103
113
104
114
from datetime import date
105
115
from platform import os
@@ -148,27 +158,43 @@ def create_fortran_module(module_name,source_folder,out_folder,prefix,ext_functi
148
158
for m in range (len (modules )):
149
159
this_module = module_name
150
160
if len (initials [m ])> 0 : this_module = this_module + "_" + initials [m ]
151
- module_file = this_module + ".f90"
161
+ if stdlib_export :
162
+ module_file = this_module + ".fypp"
163
+ else :
164
+ module_file = this_module + ".f90"
152
165
module_path = os .path .join (out_folder ,module_file )
153
166
fid = open (module_path ,"w" )
154
167
168
+ # Quad-precision directives
169
+ if stdlib_export :
170
+ fid .write ('#:include "common.fypp" \n ' )
171
+ if (initials [m ]== 'q' or initials [m ]== 'w' ): fid .write ("#!if WITH_QP \n " )
172
+
155
173
# Header
156
174
fid .write ("module {}\n " .format (this_module ))
157
175
for used in used_modules :
158
176
fid .write (INDENT + "use " + used + "\n " )
159
177
160
178
# Add top modules in the hierarchy
161
179
for n in range (m ):
180
+ if stdlib_export and (initials [n ]== 'q' or initials [n ]== 'w' ):
181
+ fid .write ("#!if WITH_QP \n " )
162
182
fid .write (INDENT + "use " + module_name + "_" + initials [n ] + "\n " )
183
+ if stdlib_export and (initials [n ]== 'q' or initials [n ]== 'w' ):
184
+ fid .write ("#!endif \n " )
163
185
164
186
fid .write (INDENT + "implicit none(type,external)\n " )
165
- fid .write (INDENT + "private\n \n \n \n " )
187
+ fid .write (INDENT + "private\n " )
166
188
167
189
# Public interface.
168
- fid .write ("\n \n \n " + INDENT + "public :: sp,dp,qp,lk,ilp\n " )
190
+ fid .write ("\n \n " + INDENT + "public :: sp,dp,qp,lk,ilp\n " )
169
191
for function in fortran_functions :
170
192
if function_in_module (initials [m ],function .old_name ):
193
+ if stdlib_export and function .is_quad_precision ():
194
+ fid .write ("#!if WITH_QP \n " )
171
195
fid .write (INDENT + "public :: " + function .new_name + "\n " )
196
+ if stdlib_export and function .is_quad_precision ():
197
+ fid .write ("#!endif \n " )
172
198
173
199
if function .new_name == "NONAME" :
174
200
print ("\n " .join (function .body ))
@@ -194,20 +220,26 @@ def create_fortran_module(module_name,source_folder,out_folder,prefix,ext_functi
194
220
for k in range (len (old_names )):
195
221
print (module_name + "_" + initials [m ]+ ": function " + old_names [k ])
196
222
197
- print_function_tree (fortran_functions ,old_names ,ext_functions ,fid ,INDENT ,MAX_LINE_LENGTH ,initials [m ])
223
+ print_function_tree (fortran_functions ,old_names ,ext_functions ,fid ,INDENT ,MAX_LINE_LENGTH , \
224
+ initials [m ],stdlib_export )
198
225
199
226
# Close module
200
227
fid .write ("\n \n \n end module {}\n " .format (this_module ))
228
+
229
+ if stdlib_export and (initials [m ]== 'q' or initials [m ]== 'w' ):
230
+ fid .write ("#!endif\n " )
231
+
201
232
fid .close ()
202
233
203
234
# Write wrapper module
204
- if split_by_initial : write_interface_module (INDENT ,out_folder ,module_name ,used_modules ,fortran_functions ,prefix )
235
+ if split_by_initial : write_interface_module (INDENT ,out_folder ,module_name ,used_modules ,fortran_functions ,\
236
+ prefix ,stdlib_export )
205
237
206
238
# Return list of all functions defined in this module, including the external ones
207
239
return fortran_functions
208
240
209
241
# Write interface module wrapping the whole library
210
- def write_interface_module (INDENT ,out_folder ,module_name ,used_modules ,fortran_functions ,prefix ):
242
+ def write_interface_module (INDENT ,out_folder ,module_name ,used_modules ,fortran_functions ,prefix , stdlib_export ):
211
243
212
244
quad_precision = True
213
245
@@ -225,18 +257,27 @@ def write_interface_module(INDENT,out_folder,module_name,used_modules,fortran_fu
225
257
226
258
interfaces .sort ()
227
259
228
- module_file = module_name + ".f90"
260
+ if stdlib_export :
261
+ module_file = module_name + ".fypp"
262
+ else :
263
+ module_file = module_name + ".f90"
229
264
module_path = os .path .join (out_folder ,module_file )
230
265
231
266
fid = open (module_path ,"w" )
267
+ if stdlib_export :
268
+ fid .write ('#:include "common.fypp" \n ' )
232
269
233
270
# Header
234
271
fid .write ("module {}\n " .format (module_name ))
235
272
for used in used_modules :
236
273
fid .write (INDENT + "use " + used + "\n " )
237
274
238
275
for i in initials :
276
+ if stdlib_export and i == 'q' :
277
+ fid .write ("#!if WITH_QP \n " )
239
278
fid .write (INDENT + "use {mname}_{minit}\n " .format (mname = module_name ,minit = i ))
279
+ if stdlib_export and i == 'q' :
280
+ fid .write ("#!endif \n " )
240
281
fid .write (INDENT + "implicit none(type,external)\n " )
241
282
fid .write (INDENT + "public\n " )
242
283
@@ -253,19 +294,19 @@ def write_interface_module(INDENT,out_folder,module_name,used_modules,fortran_fu
253
294
if len (interf_functions )> 0 and len (interf_subroutines )> 0 :
254
295
# There are mixed subroutines and functions with the same name, so, we need to
255
296
# write two separate interfaces. Add _s and _f suffixes to differentiate between them
256
- write_interface (fid ,interfaces [j ]+ "_f" ,interf_functions ,INDENT ,prefix ,module_name )
257
- write_interface (fid ,interfaces [j ]+ "_s" ,interf_subroutines ,INDENT ,prefix ,module_name )
297
+ write_interface (fid ,interfaces [j ]+ "_f" ,interf_functions ,INDENT ,prefix ,module_name , stdlib_export )
298
+ write_interface (fid ,interfaces [j ]+ "_s" ,interf_subroutines ,INDENT ,prefix ,module_name , stdlib_export )
258
299
elif len (interf_functions )> 0 :
259
- write_interface (fid ,interfaces [j ],interf_functions ,INDENT ,prefix ,module_name )
300
+ write_interface (fid ,interfaces [j ],interf_functions ,INDENT ,prefix ,module_name , stdlib_export )
260
301
elif len (interf_subroutines )> 0 :
261
- write_interface (fid ,interfaces [j ],interf_subroutines ,INDENT ,prefix ,module_name )
302
+ write_interface (fid ,interfaces [j ],interf_subroutines ,INDENT ,prefix ,module_name , stdlib_export )
262
303
263
304
# Close module
264
305
fid .write ("\n \n \n end module {}\n " .format (module_name ))
265
306
fid .close ()
266
307
267
308
# write interface
268
- def write_interface (fid ,name ,functions ,INDENT ,prefix ,module_name ):
309
+ def write_interface (fid ,name ,functions ,INDENT ,prefix ,module_name , stdlib_export ):
269
310
270
311
MAX_LINE_LENGTH = 100 # No line limits for the comments
271
312
@@ -310,12 +351,17 @@ def write_interface(fid,name,functions,INDENT,prefix,module_name):
310
351
311
352
fid .write ("#else\n " )
312
353
354
+ elif stdlib_export :
355
+ # Quad precision export
356
+ fid .write ("#!if WITH_QP\n " )
313
357
314
358
# Local implementation
315
359
fid .write (INDENT * 3 + "module procedure {}\n " .format (f .new_name ))
316
360
317
361
if has_external :
318
362
fid .write ("#endif\n " )
363
+ elif stdlib_export :
364
+ fid .write ("#!endif\n " )
319
365
320
366
# Close interface
321
367
fid .write (INDENT * 2 + "end interface {}\n \n \n " .format (name ))
@@ -453,41 +499,6 @@ def double_to_quad(lines,initial,newinit,prefix,procedure_name=None):
453
499
454
500
return whole
455
501
456
-
457
- # Double precision of the current module, 64-bit -> 128-bit
458
- def quad_precision_module (module_name ,out_folder ,initial ,prefix ):
459
-
460
- import re
461
-
462
- if initial == 'd' :
463
- newinit = 'q'
464
- elif initial == 'z' :
465
- newinit = 'w'
466
- else :
467
- print (initial + "is not a 64-bit type initial" )
468
- exit (1 )
469
-
470
- dble_module = module_name + "_" + initial
471
- quad_module = module_name + "_" + newinit
472
-
473
- dble_file = dble_module + ".f90"
474
- module_path = os .path .join (out_folder ,dble_file )
475
- out_path = os .path .join (out_folder ,quad_module + ".f90" )
476
-
477
- # Load whole module into a file
478
- dble_file = []
479
- with open (module_path , 'r' ) as file :
480
- for line in file :
481
- dble_file .append (line .rstrip ())
482
-
483
- whole = double_to_quad (dble_file ,initial ,newinit ,prefix )
484
-
485
- # Write to disk
486
- fid = open (out_path ,"w" )
487
- fid .write ('\n ' .join (whole ))
488
- fid .close ()
489
-
490
-
491
502
def function_module_initial (function_name ):
492
503
initials = ['aux' ,'c' ,'s' ,'d' ,'z' ]
493
504
@@ -763,7 +774,7 @@ def has_nonpure_deps(function,functions=None):
763
774
return has_nonpure_deps
764
775
765
776
# Print function tree in a dependency-suitable way
766
- def print_function_tree (functions ,fun_names ,ext_funs ,fid ,INDENT ,MAX_LINE_LENGTH ,initial ):
777
+ def print_function_tree (functions ,fun_names ,ext_funs ,fid ,INDENT ,MAX_LINE_LENGTH ,initial , stdlib_export ):
767
778
768
779
ext_fun_names = fun_names [len (functions ):]
769
780
@@ -816,13 +827,19 @@ def print_function_tree(functions,fun_names,ext_funs,fid,INDENT,MAX_LINE_LENGTH,
816
827
elif functions [dep ].printed :
817
828
nprinted += 1
818
829
819
- #print("function "+functions[i].old_name+" printed="+str(nprinted)+", len="+str(len(functions[i].deps)))
820
-
830
+ # Write actual function
821
831
if nprinted == len (functions [i ].deps ) or attempt >= MAXIT :
832
+
833
+ if functions [i ].is_quad_precision () and stdlib_export :
834
+ fid .write ("\n #!if WITH_QP \n " )
835
+
822
836
write_function_body (fid ,functions [i ].header ," " * header_indentation (functions [i ].body ),MAX_LINE_LENGTH ,False )
823
837
write_function_body (fid ,functions [i ].body ,INDENT ,MAX_LINE_LENGTH ,True )
824
838
functions [i ].printed = True
825
839
840
+ if functions [i ].is_quad_precision () and stdlib_export :
841
+ fid .write ("#!endif \n " )
842
+
826
843
827
844
# Final check
828
845
not_printed = 0
@@ -3241,13 +3258,13 @@ def parse_interfaces(Sources):
3241
3258
"../assets/reference_lapack/BLAS/SRC" ,"../src" ,\
3242
3259
"stdlib_" ,\
3243
3260
funs ,\
3244
- ["stdlib_linalg_constants" ],True )
3245
- funs = create_fortran_module ("stdlib_linalg_lapack" ,\
3246
- "../assets/lapack_sources" ,\
3247
- "../src" ,\
3248
- "stdlib_" ,\
3249
- funs ,\
3250
- ["stdlib_linalg_constants" ,"stdlib_linalg_blas" ],True )
3261
+ ["stdlib_linalg_constants" ],True , True )
3262
+ # funs = create_fortran_module("stdlib_linalg_lapack",\
3263
+ # "../assets/lapack_sources",\
3264
+ # "../src",\
3265
+ # "stdlib_",\
3266
+ # funs,\
3267
+ # ["stdlib_linalg_constants","stdlib_linalg_blas"],True)
3251
3268
#create_fortran_module("stdlib_linalg_blas_test_eig","../assets/reference_lapack/TESTING/EIG","../test","stdlib_test_")
3252
3269
3253
3270
0 commit comments