Updated script that can be controled by Nodejs web app
This commit is contained in:
88
lib/python3.13/site-packages/numpy/f2py/__init__.py
Normal file
88
lib/python3.13/site-packages/numpy/f2py/__init__.py
Normal file
@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Fortran to Python Interface Generator.
|
||||
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
Permission to use, modify, and distribute this software is given under the terms
|
||||
of the NumPy License.
|
||||
|
||||
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
"""
|
||||
__all__ = ['run_main', 'get_include']
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
import os
|
||||
import warnings
|
||||
|
||||
from numpy.exceptions import VisibleDeprecationWarning
|
||||
from . import f2py2e
|
||||
from . import diagnose
|
||||
|
||||
run_main = f2py2e.run_main
|
||||
main = f2py2e.main
|
||||
|
||||
|
||||
def get_include():
|
||||
"""
|
||||
Return the directory that contains the ``fortranobject.c`` and ``.h`` files.
|
||||
|
||||
.. note::
|
||||
|
||||
This function is not needed when building an extension with
|
||||
`numpy.distutils` directly from ``.f`` and/or ``.pyf`` files
|
||||
in one go.
|
||||
|
||||
Python extension modules built with f2py-generated code need to use
|
||||
``fortranobject.c`` as a source file, and include the ``fortranobject.h``
|
||||
header. This function can be used to obtain the directory containing
|
||||
both of these files.
|
||||
|
||||
Returns
|
||||
-------
|
||||
include_path : str
|
||||
Absolute path to the directory containing ``fortranobject.c`` and
|
||||
``fortranobject.h``.
|
||||
|
||||
Notes
|
||||
-----
|
||||
.. versionadded:: 1.21.1
|
||||
|
||||
Unless the build system you are using has specific support for f2py,
|
||||
building a Python extension using a ``.pyf`` signature file is a two-step
|
||||
process. For a module ``mymod``:
|
||||
|
||||
* Step 1: run ``python -m numpy.f2py mymod.pyf --quiet``. This
|
||||
generates ``mymodmodule.c`` and (if needed)
|
||||
``mymod-f2pywrappers.f`` files next to ``mymod.pyf``.
|
||||
* Step 2: build your Python extension module. This requires the
|
||||
following source files:
|
||||
|
||||
* ``mymodmodule.c``
|
||||
* ``mymod-f2pywrappers.f`` (if it was generated in Step 1)
|
||||
* ``fortranobject.c``
|
||||
|
||||
See Also
|
||||
--------
|
||||
numpy.get_include : function that returns the numpy include directory
|
||||
|
||||
"""
|
||||
return os.path.join(os.path.dirname(__file__), 'src')
|
||||
|
||||
|
||||
def __getattr__(attr):
|
||||
|
||||
# Avoid importing things that aren't needed for building
|
||||
# which might import the main numpy module
|
||||
if attr == "test":
|
||||
from numpy._pytesttester import PytestTester
|
||||
test = PytestTester(__name__)
|
||||
return test
|
||||
|
||||
else:
|
||||
raise AttributeError("module {!r} has no attribute "
|
||||
"{!r}".format(__name__, attr))
|
||||
|
||||
|
||||
def __dir__():
|
||||
return list(globals().keys() | {"test"})
|
42
lib/python3.13/site-packages/numpy/f2py/__init__.pyi
Normal file
42
lib/python3.13/site-packages/numpy/f2py/__init__.pyi
Normal file
@ -0,0 +1,42 @@
|
||||
import os
|
||||
import subprocess
|
||||
from collections.abc import Iterable
|
||||
from typing import Literal as L, Any, overload, TypedDict
|
||||
|
||||
from numpy._pytesttester import PytestTester
|
||||
|
||||
class _F2PyDictBase(TypedDict):
|
||||
csrc: list[str]
|
||||
h: list[str]
|
||||
|
||||
class _F2PyDict(_F2PyDictBase, total=False):
|
||||
fsrc: list[str]
|
||||
ltx: list[str]
|
||||
|
||||
__all__: list[str]
|
||||
test: PytestTester
|
||||
|
||||
def run_main(comline_list: Iterable[str]) -> dict[str, _F2PyDict]: ...
|
||||
|
||||
@overload
|
||||
def compile( # type: ignore[misc]
|
||||
source: str | bytes,
|
||||
modulename: str = ...,
|
||||
extra_args: str | list[str] = ...,
|
||||
verbose: bool = ...,
|
||||
source_fn: None | str | bytes | os.PathLike[Any] = ...,
|
||||
extension: L[".f", ".f90"] = ...,
|
||||
full_output: L[False] = ...,
|
||||
) -> int: ...
|
||||
@overload
|
||||
def compile(
|
||||
source: str | bytes,
|
||||
modulename: str = ...,
|
||||
extra_args: str | list[str] = ...,
|
||||
verbose: bool = ...,
|
||||
source_fn: None | str | bytes | os.PathLike[Any] = ...,
|
||||
extension: L[".f", ".f90"] = ...,
|
||||
full_output: L[True] = ...,
|
||||
) -> subprocess.CompletedProcess[bytes]: ...
|
||||
|
||||
def get_include() -> str: ...
|
5
lib/python3.13/site-packages/numpy/f2py/__main__.py
Normal file
5
lib/python3.13/site-packages/numpy/f2py/__main__.py
Normal file
@ -0,0 +1,5 @@
|
||||
# See:
|
||||
# https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e
|
||||
from numpy.f2py.f2py2e import main
|
||||
|
||||
main()
|
1
lib/python3.13/site-packages/numpy/f2py/__version__.py
Normal file
1
lib/python3.13/site-packages/numpy/f2py/__version__.py
Normal file
@ -0,0 +1 @@
|
||||
from numpy.version import version
|
@ -0,0 +1,9 @@
|
||||
def f2py_build_generator(name):
|
||||
if name == "meson":
|
||||
from ._meson import MesonBackend
|
||||
return MesonBackend
|
||||
elif name == "distutils":
|
||||
from ._distutils import DistutilsBackend
|
||||
return DistutilsBackend
|
||||
else:
|
||||
raise ValueError(f"Unknown backend: {name}")
|
@ -0,0 +1,46 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class Backend(ABC):
|
||||
def __init__(
|
||||
self,
|
||||
modulename,
|
||||
sources,
|
||||
extra_objects,
|
||||
build_dir,
|
||||
include_dirs,
|
||||
library_dirs,
|
||||
libraries,
|
||||
define_macros,
|
||||
undef_macros,
|
||||
f2py_flags,
|
||||
sysinfo_flags,
|
||||
fc_flags,
|
||||
flib_flags,
|
||||
setup_flags,
|
||||
remove_build_dir,
|
||||
extra_dat,
|
||||
):
|
||||
self.modulename = modulename
|
||||
self.sources = sources
|
||||
self.extra_objects = extra_objects
|
||||
self.build_dir = build_dir
|
||||
self.include_dirs = include_dirs
|
||||
self.library_dirs = library_dirs
|
||||
self.libraries = libraries
|
||||
self.define_macros = define_macros
|
||||
self.undef_macros = undef_macros
|
||||
self.f2py_flags = f2py_flags
|
||||
self.sysinfo_flags = sysinfo_flags
|
||||
self.fc_flags = fc_flags
|
||||
self.flib_flags = flib_flags
|
||||
self.setup_flags = setup_flags
|
||||
self.remove_build_dir = remove_build_dir
|
||||
self.extra_dat = extra_dat
|
||||
|
||||
@abstractmethod
|
||||
def compile(self) -> None:
|
||||
"""Compile the wrapper."""
|
||||
pass
|
@ -0,0 +1,75 @@
|
||||
from ._backend import Backend
|
||||
|
||||
from numpy.distutils.core import setup, Extension
|
||||
from numpy.distutils.system_info import get_info
|
||||
from numpy.distutils.misc_util import dict_append
|
||||
from numpy.exceptions import VisibleDeprecationWarning
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import warnings
|
||||
|
||||
|
||||
class DistutilsBackend(Backend):
|
||||
def __init__(sef, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"\ndistutils has been deprecated since NumPy 1.26.x\n"
|
||||
"Use the Meson backend instead, or generate wrappers"
|
||||
" without -c and use a custom build script",
|
||||
VisibleDeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def compile(self):
|
||||
num_info = {}
|
||||
if num_info:
|
||||
self.include_dirs.extend(num_info.get("include_dirs", []))
|
||||
ext_args = {
|
||||
"name": self.modulename,
|
||||
"sources": self.sources,
|
||||
"include_dirs": self.include_dirs,
|
||||
"library_dirs": self.library_dirs,
|
||||
"libraries": self.libraries,
|
||||
"define_macros": self.define_macros,
|
||||
"undef_macros": self.undef_macros,
|
||||
"extra_objects": self.extra_objects,
|
||||
"f2py_options": self.f2py_flags,
|
||||
}
|
||||
|
||||
if self.sysinfo_flags:
|
||||
for n in self.sysinfo_flags:
|
||||
i = get_info(n)
|
||||
if not i:
|
||||
print(
|
||||
f"No {repr(n)} resources found"
|
||||
"in system (try `f2py --help-link`)"
|
||||
)
|
||||
dict_append(ext_args, **i)
|
||||
|
||||
ext = Extension(**ext_args)
|
||||
|
||||
sys.argv = [sys.argv[0]] + self.setup_flags
|
||||
sys.argv.extend(
|
||||
[
|
||||
"build",
|
||||
"--build-temp",
|
||||
self.build_dir,
|
||||
"--build-base",
|
||||
self.build_dir,
|
||||
"--build-platlib",
|
||||
".",
|
||||
"--disable-optimization",
|
||||
]
|
||||
)
|
||||
|
||||
if self.fc_flags:
|
||||
sys.argv.extend(["config_fc"] + self.fc_flags)
|
||||
if self.flib_flags:
|
||||
sys.argv.extend(["build_ext"] + self.flib_flags)
|
||||
|
||||
setup(ext_modules=[ext])
|
||||
|
||||
if self.remove_build_dir and os.path.exists(self.build_dir):
|
||||
print(f"Removing build directory {self.build_dir}")
|
||||
shutil.rmtree(self.build_dir)
|
234
lib/python3.13/site-packages/numpy/f2py/_backends/_meson.py
Normal file
234
lib/python3.13/site-packages/numpy/f2py/_backends/_meson.py
Normal file
@ -0,0 +1,234 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import errno
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
from ._backend import Backend
|
||||
from string import Template
|
||||
from itertools import chain
|
||||
|
||||
import warnings
|
||||
|
||||
|
||||
class MesonTemplate:
|
||||
"""Template meson build file generation class."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
modulename: str,
|
||||
sources: list[Path],
|
||||
deps: list[str],
|
||||
libraries: list[str],
|
||||
library_dirs: list[Path],
|
||||
include_dirs: list[Path],
|
||||
object_files: list[Path],
|
||||
linker_args: list[str],
|
||||
fortran_args: list[str],
|
||||
build_type: str,
|
||||
python_exe: str,
|
||||
):
|
||||
self.modulename = modulename
|
||||
self.build_template_path = (
|
||||
Path(__file__).parent.absolute() / "meson.build.template"
|
||||
)
|
||||
self.sources = sources
|
||||
self.deps = deps
|
||||
self.libraries = libraries
|
||||
self.library_dirs = library_dirs
|
||||
if include_dirs is not None:
|
||||
self.include_dirs = include_dirs
|
||||
else:
|
||||
self.include_dirs = []
|
||||
self.substitutions = {}
|
||||
self.objects = object_files
|
||||
# Convert args to '' wrapped variant for meson
|
||||
self.fortran_args = [
|
||||
f"'{x}'" if not (x.startswith("'") and x.endswith("'")) else x
|
||||
for x in fortran_args
|
||||
]
|
||||
self.pipeline = [
|
||||
self.initialize_template,
|
||||
self.sources_substitution,
|
||||
self.deps_substitution,
|
||||
self.include_substitution,
|
||||
self.libraries_substitution,
|
||||
self.fortran_args_substitution,
|
||||
]
|
||||
self.build_type = build_type
|
||||
self.python_exe = python_exe
|
||||
self.indent = " " * 21
|
||||
|
||||
def meson_build_template(self) -> str:
|
||||
if not self.build_template_path.is_file():
|
||||
raise FileNotFoundError(
|
||||
errno.ENOENT,
|
||||
"Meson build template"
|
||||
f" {self.build_template_path.absolute()}"
|
||||
" does not exist.",
|
||||
)
|
||||
return self.build_template_path.read_text()
|
||||
|
||||
def initialize_template(self) -> None:
|
||||
self.substitutions["modulename"] = self.modulename
|
||||
self.substitutions["buildtype"] = self.build_type
|
||||
self.substitutions["python"] = self.python_exe
|
||||
|
||||
def sources_substitution(self) -> None:
|
||||
self.substitutions["source_list"] = ",\n".join(
|
||||
[f"{self.indent}'''{source}'''," for source in self.sources]
|
||||
)
|
||||
|
||||
def deps_substitution(self) -> None:
|
||||
self.substitutions["dep_list"] = f",\n{self.indent}".join(
|
||||
[f"{self.indent}dependency('{dep}')," for dep in self.deps]
|
||||
)
|
||||
|
||||
def libraries_substitution(self) -> None:
|
||||
self.substitutions["lib_dir_declarations"] = "\n".join(
|
||||
[
|
||||
f"lib_dir_{i} = declare_dependency(link_args : ['''-L{lib_dir}'''])"
|
||||
for i, lib_dir in enumerate(self.library_dirs)
|
||||
]
|
||||
)
|
||||
|
||||
self.substitutions["lib_declarations"] = "\n".join(
|
||||
[
|
||||
f"{lib.replace('.','_')} = declare_dependency(link_args : ['-l{lib}'])"
|
||||
for lib in self.libraries
|
||||
]
|
||||
)
|
||||
|
||||
self.substitutions["lib_list"] = f"\n{self.indent}".join(
|
||||
[f"{self.indent}{lib.replace('.','_')}," for lib in self.libraries]
|
||||
)
|
||||
self.substitutions["lib_dir_list"] = f"\n{self.indent}".join(
|
||||
[f"{self.indent}lib_dir_{i}," for i in range(len(self.library_dirs))]
|
||||
)
|
||||
|
||||
def include_substitution(self) -> None:
|
||||
self.substitutions["inc_list"] = f",\n{self.indent}".join(
|
||||
[f"{self.indent}'''{inc}'''," for inc in self.include_dirs]
|
||||
)
|
||||
|
||||
def fortran_args_substitution(self) -> None:
|
||||
if self.fortran_args:
|
||||
self.substitutions["fortran_args"] = (
|
||||
f"{self.indent}fortran_args: [{', '.join([arg for arg in self.fortran_args])}],"
|
||||
)
|
||||
else:
|
||||
self.substitutions["fortran_args"] = ""
|
||||
|
||||
def generate_meson_build(self):
|
||||
for node in self.pipeline:
|
||||
node()
|
||||
template = Template(self.meson_build_template())
|
||||
meson_build = template.substitute(self.substitutions)
|
||||
meson_build = re.sub(r",,", ",", meson_build)
|
||||
return meson_build
|
||||
|
||||
|
||||
class MesonBackend(Backend):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.dependencies = self.extra_dat.get("dependencies", [])
|
||||
self.meson_build_dir = "bbdir"
|
||||
self.build_type = (
|
||||
"debug" if any("debug" in flag for flag in self.fc_flags) else "release"
|
||||
)
|
||||
self.fc_flags = _get_flags(self.fc_flags)
|
||||
|
||||
def _move_exec_to_root(self, build_dir: Path):
|
||||
walk_dir = Path(build_dir) / self.meson_build_dir
|
||||
path_objects = chain(
|
||||
walk_dir.glob(f"{self.modulename}*.so"),
|
||||
walk_dir.glob(f"{self.modulename}*.pyd"),
|
||||
)
|
||||
# Same behavior as distutils
|
||||
# https://github.com/numpy/numpy/issues/24874#issuecomment-1835632293
|
||||
for path_object in path_objects:
|
||||
dest_path = Path.cwd() / path_object.name
|
||||
if dest_path.exists():
|
||||
dest_path.unlink()
|
||||
shutil.copy2(path_object, dest_path)
|
||||
os.remove(path_object)
|
||||
|
||||
def write_meson_build(self, build_dir: Path) -> None:
|
||||
"""Writes the meson build file at specified location"""
|
||||
meson_template = MesonTemplate(
|
||||
self.modulename,
|
||||
self.sources,
|
||||
self.dependencies,
|
||||
self.libraries,
|
||||
self.library_dirs,
|
||||
self.include_dirs,
|
||||
self.extra_objects,
|
||||
self.flib_flags,
|
||||
self.fc_flags,
|
||||
self.build_type,
|
||||
sys.executable,
|
||||
)
|
||||
src = meson_template.generate_meson_build()
|
||||
Path(build_dir).mkdir(parents=True, exist_ok=True)
|
||||
meson_build_file = Path(build_dir) / "meson.build"
|
||||
meson_build_file.write_text(src)
|
||||
return meson_build_file
|
||||
|
||||
def _run_subprocess_command(self, command, cwd):
|
||||
subprocess.run(command, cwd=cwd, check=True)
|
||||
|
||||
def run_meson(self, build_dir: Path):
|
||||
setup_command = ["meson", "setup", self.meson_build_dir]
|
||||
self._run_subprocess_command(setup_command, build_dir)
|
||||
compile_command = ["meson", "compile", "-C", self.meson_build_dir]
|
||||
self._run_subprocess_command(compile_command, build_dir)
|
||||
|
||||
def compile(self) -> None:
|
||||
self.sources = _prepare_sources(self.modulename, self.sources, self.build_dir)
|
||||
self.write_meson_build(self.build_dir)
|
||||
self.run_meson(self.build_dir)
|
||||
self._move_exec_to_root(self.build_dir)
|
||||
|
||||
|
||||
def _prepare_sources(mname, sources, bdir):
|
||||
extended_sources = sources.copy()
|
||||
Path(bdir).mkdir(parents=True, exist_ok=True)
|
||||
# Copy sources
|
||||
for source in sources:
|
||||
if Path(source).exists() and Path(source).is_file():
|
||||
shutil.copy(source, bdir)
|
||||
generated_sources = [
|
||||
Path(f"{mname}module.c"),
|
||||
Path(f"{mname}-f2pywrappers2.f90"),
|
||||
Path(f"{mname}-f2pywrappers.f"),
|
||||
]
|
||||
bdir = Path(bdir)
|
||||
for generated_source in generated_sources:
|
||||
if generated_source.exists():
|
||||
shutil.copy(generated_source, bdir / generated_source.name)
|
||||
extended_sources.append(generated_source.name)
|
||||
generated_source.unlink()
|
||||
extended_sources = [
|
||||
Path(source).name
|
||||
for source in extended_sources
|
||||
if not Path(source).suffix == ".pyf"
|
||||
]
|
||||
return extended_sources
|
||||
|
||||
|
||||
def _get_flags(fc_flags):
|
||||
flag_values = []
|
||||
flag_pattern = re.compile(r"--f(77|90)flags=(.*)")
|
||||
for flag in fc_flags:
|
||||
match_result = flag_pattern.match(flag)
|
||||
if match_result:
|
||||
values = match_result.group(2).strip().split()
|
||||
values = [val.strip("'\"") for val in values]
|
||||
flag_values.extend(values)
|
||||
# Hacky way to preserve order of flags
|
||||
unique_flags = list(dict.fromkeys(flag_values))
|
||||
return unique_flags
|
@ -0,0 +1,55 @@
|
||||
project('${modulename}',
|
||||
['c', 'fortran'],
|
||||
version : '0.1',
|
||||
meson_version: '>= 1.1.0',
|
||||
default_options : [
|
||||
'warning_level=1',
|
||||
'buildtype=${buildtype}'
|
||||
])
|
||||
fc = meson.get_compiler('fortran')
|
||||
|
||||
py = import('python').find_installation('''${python}''', pure: false)
|
||||
py_dep = py.dependency()
|
||||
|
||||
incdir_numpy = run_command(py,
|
||||
['-c', 'import os; os.chdir(".."); import numpy; print(numpy.get_include())'],
|
||||
check : true
|
||||
).stdout().strip()
|
||||
|
||||
incdir_f2py = run_command(py,
|
||||
['-c', 'import os; os.chdir(".."); import numpy.f2py; print(numpy.f2py.get_include())'],
|
||||
check : true
|
||||
).stdout().strip()
|
||||
|
||||
inc_np = include_directories(incdir_numpy)
|
||||
np_dep = declare_dependency(include_directories: inc_np)
|
||||
|
||||
incdir_f2py = incdir_numpy / '..' / '..' / 'f2py' / 'src'
|
||||
inc_f2py = include_directories(incdir_f2py)
|
||||
fortranobject_c = incdir_f2py / 'fortranobject.c'
|
||||
|
||||
inc_np = include_directories(incdir_numpy, incdir_f2py)
|
||||
# gh-25000
|
||||
quadmath_dep = fc.find_library('quadmath', required: false)
|
||||
|
||||
${lib_declarations}
|
||||
${lib_dir_declarations}
|
||||
|
||||
py.extension_module('${modulename}',
|
||||
[
|
||||
${source_list},
|
||||
fortranobject_c
|
||||
],
|
||||
include_directories: [
|
||||
inc_np,
|
||||
${inc_list}
|
||||
],
|
||||
dependencies : [
|
||||
py_dep,
|
||||
quadmath_dep,
|
||||
${dep_list}
|
||||
${lib_list}
|
||||
${lib_dir_list}
|
||||
],
|
||||
${fortran_args}
|
||||
install : true)
|
62
lib/python3.13/site-packages/numpy/f2py/_isocbind.py
Normal file
62
lib/python3.13/site-packages/numpy/f2py/_isocbind.py
Normal file
@ -0,0 +1,62 @@
|
||||
"""
|
||||
ISO_C_BINDING maps for f2py2e.
|
||||
Only required declarations/macros/functions will be used.
|
||||
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
Permission to use, modify, and distribute this software is given under the
|
||||
terms of the NumPy License.
|
||||
|
||||
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
"""
|
||||
# These map to keys in c2py_map, via forced casting for now, see gh-25229
|
||||
iso_c_binding_map = {
|
||||
'integer': {
|
||||
'c_int': 'int',
|
||||
'c_short': 'short', # 'short' <=> 'int' for now
|
||||
'c_long': 'long', # 'long' <=> 'int' for now
|
||||
'c_long_long': 'long_long',
|
||||
'c_signed_char': 'signed_char',
|
||||
'c_size_t': 'unsigned', # size_t <=> 'unsigned' for now
|
||||
'c_int8_t': 'signed_char', # int8_t <=> 'signed_char' for now
|
||||
'c_int16_t': 'short', # int16_t <=> 'short' for now
|
||||
'c_int32_t': 'int', # int32_t <=> 'int' for now
|
||||
'c_int64_t': 'long_long',
|
||||
'c_int_least8_t': 'signed_char', # int_least8_t <=> 'signed_char' for now
|
||||
'c_int_least16_t': 'short', # int_least16_t <=> 'short' for now
|
||||
'c_int_least32_t': 'int', # int_least32_t <=> 'int' for now
|
||||
'c_int_least64_t': 'long_long',
|
||||
'c_int_fast8_t': 'signed_char', # int_fast8_t <=> 'signed_char' for now
|
||||
'c_int_fast16_t': 'short', # int_fast16_t <=> 'short' for now
|
||||
'c_int_fast32_t': 'int', # int_fast32_t <=> 'int' for now
|
||||
'c_int_fast64_t': 'long_long',
|
||||
'c_intmax_t': 'long_long', # intmax_t <=> 'long_long' for now
|
||||
'c_intptr_t': 'long', # intptr_t <=> 'long' for now
|
||||
'c_ptrdiff_t': 'long', # ptrdiff_t <=> 'long' for now
|
||||
},
|
||||
'real': {
|
||||
'c_float': 'float',
|
||||
'c_double': 'double',
|
||||
'c_long_double': 'long_double'
|
||||
},
|
||||
'complex': {
|
||||
'c_float_complex': 'complex_float',
|
||||
'c_double_complex': 'complex_double',
|
||||
'c_long_double_complex': 'complex_long_double'
|
||||
},
|
||||
'logical': {
|
||||
'c_bool': 'unsigned_char' # _Bool <=> 'unsigned_char' for now
|
||||
},
|
||||
'character': {
|
||||
'c_char': 'char'
|
||||
}
|
||||
}
|
||||
|
||||
# TODO: See gh-25229
|
||||
isoc_c2pycode_map = {}
|
||||
iso_c2py_map = {}
|
||||
|
||||
isoc_kindmap = {}
|
||||
for fortran_type, c_type_dict in iso_c_binding_map.items():
|
||||
for c_type in c_type_dict.keys():
|
||||
isoc_kindmap[c_type] = fortran_type
|
239
lib/python3.13/site-packages/numpy/f2py/_src_pyf.py
Normal file
239
lib/python3.13/site-packages/numpy/f2py/_src_pyf.py
Normal file
@ -0,0 +1,239 @@
|
||||
import re
|
||||
|
||||
# START OF CODE VENDORED FROM `numpy.distutils.from_template`
|
||||
#############################################################
|
||||
"""
|
||||
process_file(filename)
|
||||
|
||||
takes templated file .xxx.src and produces .xxx file where .xxx
|
||||
is .pyf .f90 or .f using the following template rules:
|
||||
|
||||
'<..>' denotes a template.
|
||||
|
||||
All function and subroutine blocks in a source file with names that
|
||||
contain '<..>' will be replicated according to the rules in '<..>'.
|
||||
|
||||
The number of comma-separated words in '<..>' will determine the number of
|
||||
replicates.
|
||||
|
||||
'<..>' may have two different forms, named and short. For example,
|
||||
|
||||
named:
|
||||
<p=d,s,z,c> where anywhere inside a block '<p>' will be replaced with
|
||||
'd', 's', 'z', and 'c' for each replicate of the block.
|
||||
|
||||
<_c> is already defined: <_c=s,d,c,z>
|
||||
<_t> is already defined: <_t=real,double precision,complex,double complex>
|
||||
|
||||
short:
|
||||
<s,d,c,z>, a short form of the named, useful when no <p> appears inside
|
||||
a block.
|
||||
|
||||
In general, '<..>' contains a comma separated list of arbitrary
|
||||
expressions. If these expression must contain a comma|leftarrow|rightarrow,
|
||||
then prepend the comma|leftarrow|rightarrow with a backslash.
|
||||
|
||||
If an expression matches '\\<index>' then it will be replaced
|
||||
by <index>-th expression.
|
||||
|
||||
Note that all '<..>' forms in a block must have the same number of
|
||||
comma-separated entries.
|
||||
|
||||
Predefined named template rules:
|
||||
<prefix=s,d,c,z>
|
||||
<ftype=real,double precision,complex,double complex>
|
||||
<ftypereal=real,double precision,\\0,\\1>
|
||||
<ctype=float,double,complex_float,complex_double>
|
||||
<ctypereal=float,double,\\0,\\1>
|
||||
"""
|
||||
|
||||
routine_start_re = re.compile(r'(\n|\A)(( (\$|\*))|)\s*(subroutine|function)\b', re.I)
|
||||
routine_end_re = re.compile(r'\n\s*end\s*(subroutine|function)\b.*(\n|\Z)', re.I)
|
||||
function_start_re = re.compile(r'\n (\$|\*)\s*function\b', re.I)
|
||||
|
||||
def parse_structure(astr):
|
||||
""" Return a list of tuples for each function or subroutine each
|
||||
tuple is the start and end of a subroutine or function to be
|
||||
expanded.
|
||||
"""
|
||||
|
||||
spanlist = []
|
||||
ind = 0
|
||||
while True:
|
||||
m = routine_start_re.search(astr, ind)
|
||||
if m is None:
|
||||
break
|
||||
start = m.start()
|
||||
if function_start_re.match(astr, start, m.end()):
|
||||
while True:
|
||||
i = astr.rfind('\n', ind, start)
|
||||
if i==-1:
|
||||
break
|
||||
start = i
|
||||
if astr[i:i+7]!='\n $':
|
||||
break
|
||||
start += 1
|
||||
m = routine_end_re.search(astr, m.end())
|
||||
ind = end = m and m.end()-1 or len(astr)
|
||||
spanlist.append((start, end))
|
||||
return spanlist
|
||||
|
||||
template_re = re.compile(r"<\s*(\w[\w\d]*)\s*>")
|
||||
named_re = re.compile(r"<\s*(\w[\w\d]*)\s*=\s*(.*?)\s*>")
|
||||
list_re = re.compile(r"<\s*((.*?))\s*>")
|
||||
|
||||
def find_repl_patterns(astr):
|
||||
reps = named_re.findall(astr)
|
||||
names = {}
|
||||
for rep in reps:
|
||||
name = rep[0].strip() or unique_key(names)
|
||||
repl = rep[1].replace(r'\,', '@comma@')
|
||||
thelist = conv(repl)
|
||||
names[name] = thelist
|
||||
return names
|
||||
|
||||
def find_and_remove_repl_patterns(astr):
|
||||
names = find_repl_patterns(astr)
|
||||
astr = re.subn(named_re, '', astr)[0]
|
||||
return astr, names
|
||||
|
||||
item_re = re.compile(r"\A\\(?P<index>\d+)\Z")
|
||||
def conv(astr):
|
||||
b = astr.split(',')
|
||||
l = [x.strip() for x in b]
|
||||
for i in range(len(l)):
|
||||
m = item_re.match(l[i])
|
||||
if m:
|
||||
j = int(m.group('index'))
|
||||
l[i] = l[j]
|
||||
return ','.join(l)
|
||||
|
||||
def unique_key(adict):
|
||||
""" Obtain a unique key given a dictionary."""
|
||||
allkeys = list(adict.keys())
|
||||
done = False
|
||||
n = 1
|
||||
while not done:
|
||||
newkey = '__l%s' % (n)
|
||||
if newkey in allkeys:
|
||||
n += 1
|
||||
else:
|
||||
done = True
|
||||
return newkey
|
||||
|
||||
|
||||
template_name_re = re.compile(r'\A\s*(\w[\w\d]*)\s*\Z')
|
||||
def expand_sub(substr, names):
|
||||
substr = substr.replace(r'\>', '@rightarrow@')
|
||||
substr = substr.replace(r'\<', '@leftarrow@')
|
||||
lnames = find_repl_patterns(substr)
|
||||
substr = named_re.sub(r"<\1>", substr) # get rid of definition templates
|
||||
|
||||
def listrepl(mobj):
|
||||
thelist = conv(mobj.group(1).replace(r'\,', '@comma@'))
|
||||
if template_name_re.match(thelist):
|
||||
return "<%s>" % (thelist)
|
||||
name = None
|
||||
for key in lnames.keys(): # see if list is already in dictionary
|
||||
if lnames[key] == thelist:
|
||||
name = key
|
||||
if name is None: # this list is not in the dictionary yet
|
||||
name = unique_key(lnames)
|
||||
lnames[name] = thelist
|
||||
return "<%s>" % name
|
||||
|
||||
substr = list_re.sub(listrepl, substr) # convert all lists to named templates
|
||||
# newnames are constructed as needed
|
||||
|
||||
numsubs = None
|
||||
base_rule = None
|
||||
rules = {}
|
||||
for r in template_re.findall(substr):
|
||||
if r not in rules:
|
||||
thelist = lnames.get(r, names.get(r, None))
|
||||
if thelist is None:
|
||||
raise ValueError('No replicates found for <%s>' % (r))
|
||||
if r not in names and not thelist.startswith('_'):
|
||||
names[r] = thelist
|
||||
rule = [i.replace('@comma@', ',') for i in thelist.split(',')]
|
||||
num = len(rule)
|
||||
|
||||
if numsubs is None:
|
||||
numsubs = num
|
||||
rules[r] = rule
|
||||
base_rule = r
|
||||
elif num == numsubs:
|
||||
rules[r] = rule
|
||||
else:
|
||||
print("Mismatch in number of replacements (base <{}={}>) "
|
||||
"for <{}={}>. Ignoring.".format(base_rule, ','.join(rules[base_rule]), r, thelist))
|
||||
if not rules:
|
||||
return substr
|
||||
|
||||
def namerepl(mobj):
|
||||
name = mobj.group(1)
|
||||
return rules.get(name, (k+1)*[name])[k]
|
||||
|
||||
newstr = ''
|
||||
for k in range(numsubs):
|
||||
newstr += template_re.sub(namerepl, substr) + '\n\n'
|
||||
|
||||
newstr = newstr.replace('@rightarrow@', '>')
|
||||
newstr = newstr.replace('@leftarrow@', '<')
|
||||
return newstr
|
||||
|
||||
def process_str(allstr):
|
||||
newstr = allstr
|
||||
writestr = ''
|
||||
|
||||
struct = parse_structure(newstr)
|
||||
|
||||
oldend = 0
|
||||
names = {}
|
||||
names.update(_special_names)
|
||||
for sub in struct:
|
||||
cleanedstr, defs = find_and_remove_repl_patterns(newstr[oldend:sub[0]])
|
||||
writestr += cleanedstr
|
||||
names.update(defs)
|
||||
writestr += expand_sub(newstr[sub[0]:sub[1]], names)
|
||||
oldend = sub[1]
|
||||
writestr += newstr[oldend:]
|
||||
|
||||
return writestr
|
||||
|
||||
include_src_re = re.compile(r"(\n|\A)\s*include\s*['\"](?P<name>[\w\d./\\]+\.src)['\"]", re.I)
|
||||
|
||||
def resolve_includes(source):
|
||||
d = os.path.dirname(source)
|
||||
with open(source) as fid:
|
||||
lines = []
|
||||
for line in fid:
|
||||
m = include_src_re.match(line)
|
||||
if m:
|
||||
fn = m.group('name')
|
||||
if not os.path.isabs(fn):
|
||||
fn = os.path.join(d, fn)
|
||||
if os.path.isfile(fn):
|
||||
lines.extend(resolve_includes(fn))
|
||||
else:
|
||||
lines.append(line)
|
||||
else:
|
||||
lines.append(line)
|
||||
return lines
|
||||
|
||||
def process_file(source):
|
||||
lines = resolve_includes(source)
|
||||
return process_str(''.join(lines))
|
||||
|
||||
_special_names = find_repl_patterns('''
|
||||
<_c=s,d,c,z>
|
||||
<_t=real,double precision,complex,double complex>
|
||||
<prefix=s,d,c,z>
|
||||
<ftype=real,double precision,complex,double complex>
|
||||
<ctype=float,double,complex_float,complex_double>
|
||||
<ftypereal=real,double precision,\\0,\\1>
|
||||
<ctypereal=float,double,\\0,\\1>
|
||||
''')
|
||||
|
||||
# END OF CODE VENDORED FROM `numpy.distutils.from_template`
|
||||
###########################################################
|
996
lib/python3.13/site-packages/numpy/f2py/auxfuncs.py
Normal file
996
lib/python3.13/site-packages/numpy/f2py/auxfuncs.py
Normal file
@ -0,0 +1,996 @@
|
||||
"""
|
||||
Auxiliary functions for f2py2e.
|
||||
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
Permission to use, modify, and distribute this software is given under the
|
||||
terms of the NumPy (BSD style) LICENSE.
|
||||
|
||||
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
"""
|
||||
import pprint
|
||||
import sys
|
||||
import re
|
||||
import types
|
||||
from functools import reduce
|
||||
from copy import deepcopy
|
||||
|
||||
from . import __version__
|
||||
from . import cfuncs
|
||||
from .cfuncs import errmess
|
||||
|
||||
__all__ = [
|
||||
'applyrules', 'debugcapi', 'dictappend', 'errmess', 'gentitle',
|
||||
'getargs2', 'getcallprotoargument', 'getcallstatement',
|
||||
'getfortranname', 'getpymethoddef', 'getrestdoc', 'getusercode',
|
||||
'getusercode1', 'getdimension', 'hasbody', 'hascallstatement', 'hascommon',
|
||||
'hasexternals', 'hasinitvalue', 'hasnote', 'hasresultnote',
|
||||
'isallocatable', 'isarray', 'isarrayofstrings',
|
||||
'ischaracter', 'ischaracterarray', 'ischaracter_or_characterarray',
|
||||
'iscomplex',
|
||||
'iscomplexarray', 'iscomplexfunction', 'iscomplexfunction_warn',
|
||||
'isdouble', 'isdummyroutine', 'isexternal', 'isfunction',
|
||||
'isfunction_wrap', 'isint1', 'isint1array', 'isinteger', 'isintent_aux',
|
||||
'isintent_c', 'isintent_callback', 'isintent_copy', 'isintent_dict',
|
||||
'isintent_hide', 'isintent_in', 'isintent_inout', 'isintent_inplace',
|
||||
'isintent_nothide', 'isintent_out', 'isintent_overwrite', 'islogical',
|
||||
'islogicalfunction', 'islong_complex', 'islong_double',
|
||||
'islong_doublefunction', 'islong_long', 'islong_longfunction',
|
||||
'ismodule', 'ismoduleroutine', 'isoptional', 'isprivate', 'isvariable',
|
||||
'isrequired', 'isroutine', 'isscalar', 'issigned_long_longarray',
|
||||
'isstring', 'isstringarray', 'isstring_or_stringarray', 'isstringfunction',
|
||||
'issubroutine', 'get_f2py_modulename', 'issubroutine_wrap', 'isthreadsafe',
|
||||
'isunsigned', 'isunsigned_char', 'isunsigned_chararray',
|
||||
'isunsigned_long_long', 'isunsigned_long_longarray', 'isunsigned_short',
|
||||
'isunsigned_shortarray', 'l_and', 'l_not', 'l_or', 'outmess', 'replace',
|
||||
'show', 'stripcomma', 'throw_error', 'isattr_value', 'getuseblocks',
|
||||
'process_f2cmap_dict'
|
||||
]
|
||||
|
||||
|
||||
f2py_version = __version__.version
|
||||
|
||||
|
||||
show = pprint.pprint
|
||||
|
||||
options = {}
|
||||
debugoptions = []
|
||||
wrapfuncs = 1
|
||||
|
||||
|
||||
def outmess(t):
|
||||
if options.get('verbose', 1):
|
||||
sys.stdout.write(t)
|
||||
|
||||
|
||||
def debugcapi(var):
|
||||
return 'capi' in debugoptions
|
||||
|
||||
|
||||
def _ischaracter(var):
|
||||
return 'typespec' in var and var['typespec'] == 'character' and \
|
||||
not isexternal(var)
|
||||
|
||||
|
||||
def _isstring(var):
|
||||
return 'typespec' in var and var['typespec'] == 'character' and \
|
||||
not isexternal(var)
|
||||
|
||||
|
||||
def ischaracter_or_characterarray(var):
|
||||
return _ischaracter(var) and 'charselector' not in var
|
||||
|
||||
|
||||
def ischaracter(var):
|
||||
return ischaracter_or_characterarray(var) and not isarray(var)
|
||||
|
||||
|
||||
def ischaracterarray(var):
|
||||
return ischaracter_or_characterarray(var) and isarray(var)
|
||||
|
||||
|
||||
def isstring_or_stringarray(var):
|
||||
return _ischaracter(var) and 'charselector' in var
|
||||
|
||||
|
||||
def isstring(var):
|
||||
return isstring_or_stringarray(var) and not isarray(var)
|
||||
|
||||
|
||||
def isstringarray(var):
|
||||
return isstring_or_stringarray(var) and isarray(var)
|
||||
|
||||
|
||||
def isarrayofstrings(var): # obsolete?
|
||||
# leaving out '*' for now so that `character*(*) a(m)` and `character
|
||||
# a(m,*)` are treated differently. Luckily `character**` is illegal.
|
||||
return isstringarray(var) and var['dimension'][-1] == '(*)'
|
||||
|
||||
|
||||
def isarray(var):
|
||||
return 'dimension' in var and not isexternal(var)
|
||||
|
||||
|
||||
def isscalar(var):
|
||||
return not (isarray(var) or isstring(var) or isexternal(var))
|
||||
|
||||
|
||||
def iscomplex(var):
|
||||
return isscalar(var) and \
|
||||
var.get('typespec') in ['complex', 'double complex']
|
||||
|
||||
|
||||
def islogical(var):
|
||||
return isscalar(var) and var.get('typespec') == 'logical'
|
||||
|
||||
|
||||
def isinteger(var):
|
||||
return isscalar(var) and var.get('typespec') == 'integer'
|
||||
|
||||
|
||||
def isreal(var):
|
||||
return isscalar(var) and var.get('typespec') == 'real'
|
||||
|
||||
|
||||
def get_kind(var):
|
||||
try:
|
||||
return var['kindselector']['*']
|
||||
except KeyError:
|
||||
try:
|
||||
return var['kindselector']['kind']
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
def isint1(var):
|
||||
return var.get('typespec') == 'integer' \
|
||||
and get_kind(var) == '1' and not isarray(var)
|
||||
|
||||
|
||||
def islong_long(var):
|
||||
if not isscalar(var):
|
||||
return 0
|
||||
if var.get('typespec') not in ['integer', 'logical']:
|
||||
return 0
|
||||
return get_kind(var) == '8'
|
||||
|
||||
|
||||
def isunsigned_char(var):
|
||||
if not isscalar(var):
|
||||
return 0
|
||||
if var.get('typespec') != 'integer':
|
||||
return 0
|
||||
return get_kind(var) == '-1'
|
||||
|
||||
|
||||
def isunsigned_short(var):
|
||||
if not isscalar(var):
|
||||
return 0
|
||||
if var.get('typespec') != 'integer':
|
||||
return 0
|
||||
return get_kind(var) == '-2'
|
||||
|
||||
|
||||
def isunsigned(var):
|
||||
if not isscalar(var):
|
||||
return 0
|
||||
if var.get('typespec') != 'integer':
|
||||
return 0
|
||||
return get_kind(var) == '-4'
|
||||
|
||||
|
||||
def isunsigned_long_long(var):
|
||||
if not isscalar(var):
|
||||
return 0
|
||||
if var.get('typespec') != 'integer':
|
||||
return 0
|
||||
return get_kind(var) == '-8'
|
||||
|
||||
|
||||
def isdouble(var):
|
||||
if not isscalar(var):
|
||||
return 0
|
||||
if not var.get('typespec') == 'real':
|
||||
return 0
|
||||
return get_kind(var) == '8'
|
||||
|
||||
|
||||
def islong_double(var):
|
||||
if not isscalar(var):
|
||||
return 0
|
||||
if not var.get('typespec') == 'real':
|
||||
return 0
|
||||
return get_kind(var) == '16'
|
||||
|
||||
|
||||
def islong_complex(var):
|
||||
if not iscomplex(var):
|
||||
return 0
|
||||
return get_kind(var) == '32'
|
||||
|
||||
|
||||
def iscomplexarray(var):
|
||||
return isarray(var) and \
|
||||
var.get('typespec') in ['complex', 'double complex']
|
||||
|
||||
|
||||
def isint1array(var):
|
||||
return isarray(var) and var.get('typespec') == 'integer' \
|
||||
and get_kind(var) == '1'
|
||||
|
||||
|
||||
def isunsigned_chararray(var):
|
||||
return isarray(var) and var.get('typespec') in ['integer', 'logical']\
|
||||
and get_kind(var) == '-1'
|
||||
|
||||
|
||||
def isunsigned_shortarray(var):
|
||||
return isarray(var) and var.get('typespec') in ['integer', 'logical']\
|
||||
and get_kind(var) == '-2'
|
||||
|
||||
|
||||
def isunsignedarray(var):
|
||||
return isarray(var) and var.get('typespec') in ['integer', 'logical']\
|
||||
and get_kind(var) == '-4'
|
||||
|
||||
|
||||
def isunsigned_long_longarray(var):
|
||||
return isarray(var) and var.get('typespec') in ['integer', 'logical']\
|
||||
and get_kind(var) == '-8'
|
||||
|
||||
|
||||
def issigned_chararray(var):
|
||||
return isarray(var) and var.get('typespec') in ['integer', 'logical']\
|
||||
and get_kind(var) == '1'
|
||||
|
||||
|
||||
def issigned_shortarray(var):
|
||||
return isarray(var) and var.get('typespec') in ['integer', 'logical']\
|
||||
and get_kind(var) == '2'
|
||||
|
||||
|
||||
def issigned_array(var):
|
||||
return isarray(var) and var.get('typespec') in ['integer', 'logical']\
|
||||
and get_kind(var) == '4'
|
||||
|
||||
|
||||
def issigned_long_longarray(var):
|
||||
return isarray(var) and var.get('typespec') in ['integer', 'logical']\
|
||||
and get_kind(var) == '8'
|
||||
|
||||
|
||||
def isallocatable(var):
|
||||
return 'attrspec' in var and 'allocatable' in var['attrspec']
|
||||
|
||||
|
||||
def ismutable(var):
|
||||
return not ('dimension' not in var or isstring(var))
|
||||
|
||||
|
||||
def ismoduleroutine(rout):
|
||||
return 'modulename' in rout
|
||||
|
||||
|
||||
def ismodule(rout):
|
||||
return 'block' in rout and 'module' == rout['block']
|
||||
|
||||
|
||||
def isfunction(rout):
|
||||
return 'block' in rout and 'function' == rout['block']
|
||||
|
||||
|
||||
def isfunction_wrap(rout):
|
||||
if isintent_c(rout):
|
||||
return 0
|
||||
return wrapfuncs and isfunction(rout) and (not isexternal(rout))
|
||||
|
||||
|
||||
def issubroutine(rout):
|
||||
return 'block' in rout and 'subroutine' == rout['block']
|
||||
|
||||
|
||||
def issubroutine_wrap(rout):
|
||||
if isintent_c(rout):
|
||||
return 0
|
||||
return issubroutine(rout) and hasassumedshape(rout)
|
||||
|
||||
def isattr_value(var):
|
||||
return 'value' in var.get('attrspec', [])
|
||||
|
||||
|
||||
def hasassumedshape(rout):
|
||||
if rout.get('hasassumedshape'):
|
||||
return True
|
||||
for a in rout['args']:
|
||||
for d in rout['vars'].get(a, {}).get('dimension', []):
|
||||
if d == ':':
|
||||
rout['hasassumedshape'] = True
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def requiresf90wrapper(rout):
|
||||
return ismoduleroutine(rout) or hasassumedshape(rout)
|
||||
|
||||
|
||||
def isroutine(rout):
|
||||
return isfunction(rout) or issubroutine(rout)
|
||||
|
||||
|
||||
def islogicalfunction(rout):
|
||||
if not isfunction(rout):
|
||||
return 0
|
||||
if 'result' in rout:
|
||||
a = rout['result']
|
||||
else:
|
||||
a = rout['name']
|
||||
if a in rout['vars']:
|
||||
return islogical(rout['vars'][a])
|
||||
return 0
|
||||
|
||||
|
||||
def islong_longfunction(rout):
|
||||
if not isfunction(rout):
|
||||
return 0
|
||||
if 'result' in rout:
|
||||
a = rout['result']
|
||||
else:
|
||||
a = rout['name']
|
||||
if a in rout['vars']:
|
||||
return islong_long(rout['vars'][a])
|
||||
return 0
|
||||
|
||||
|
||||
def islong_doublefunction(rout):
|
||||
if not isfunction(rout):
|
||||
return 0
|
||||
if 'result' in rout:
|
||||
a = rout['result']
|
||||
else:
|
||||
a = rout['name']
|
||||
if a in rout['vars']:
|
||||
return islong_double(rout['vars'][a])
|
||||
return 0
|
||||
|
||||
|
||||
def iscomplexfunction(rout):
|
||||
if not isfunction(rout):
|
||||
return 0
|
||||
if 'result' in rout:
|
||||
a = rout['result']
|
||||
else:
|
||||
a = rout['name']
|
||||
if a in rout['vars']:
|
||||
return iscomplex(rout['vars'][a])
|
||||
return 0
|
||||
|
||||
|
||||
def iscomplexfunction_warn(rout):
|
||||
if iscomplexfunction(rout):
|
||||
outmess("""\
|
||||
**************************************************************
|
||||
Warning: code with a function returning complex value
|
||||
may not work correctly with your Fortran compiler.
|
||||
When using GNU gcc/g77 compilers, codes should work
|
||||
correctly for callbacks with:
|
||||
f2py -c -DF2PY_CB_RETURNCOMPLEX
|
||||
**************************************************************\n""")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def isstringfunction(rout):
|
||||
if not isfunction(rout):
|
||||
return 0
|
||||
if 'result' in rout:
|
||||
a = rout['result']
|
||||
else:
|
||||
a = rout['name']
|
||||
if a in rout['vars']:
|
||||
return isstring(rout['vars'][a])
|
||||
return 0
|
||||
|
||||
|
||||
def hasexternals(rout):
|
||||
return 'externals' in rout and rout['externals']
|
||||
|
||||
|
||||
def isthreadsafe(rout):
|
||||
return 'f2pyenhancements' in rout and \
|
||||
'threadsafe' in rout['f2pyenhancements']
|
||||
|
||||
|
||||
def hasvariables(rout):
|
||||
return 'vars' in rout and rout['vars']
|
||||
|
||||
|
||||
def isoptional(var):
|
||||
return ('attrspec' in var and 'optional' in var['attrspec'] and
|
||||
'required' not in var['attrspec']) and isintent_nothide(var)
|
||||
|
||||
|
||||
def isexternal(var):
|
||||
return 'attrspec' in var and 'external' in var['attrspec']
|
||||
|
||||
|
||||
def getdimension(var):
|
||||
dimpattern = r"\((.*?)\)"
|
||||
if 'attrspec' in var.keys():
|
||||
if any('dimension' in s for s in var['attrspec']):
|
||||
return [re.findall(dimpattern, v) for v in var['attrspec']][0]
|
||||
|
||||
|
||||
def isrequired(var):
|
||||
return not isoptional(var) and isintent_nothide(var)
|
||||
|
||||
|
||||
def isintent_in(var):
|
||||
if 'intent' not in var:
|
||||
return 1
|
||||
if 'hide' in var['intent']:
|
||||
return 0
|
||||
if 'inplace' in var['intent']:
|
||||
return 0
|
||||
if 'in' in var['intent']:
|
||||
return 1
|
||||
if 'out' in var['intent']:
|
||||
return 0
|
||||
if 'inout' in var['intent']:
|
||||
return 0
|
||||
if 'outin' in var['intent']:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
def isintent_inout(var):
|
||||
return ('intent' in var and ('inout' in var['intent'] or
|
||||
'outin' in var['intent']) and 'in' not in var['intent'] and
|
||||
'hide' not in var['intent'] and 'inplace' not in var['intent'])
|
||||
|
||||
|
||||
def isintent_out(var):
|
||||
return 'out' in var.get('intent', [])
|
||||
|
||||
|
||||
def isintent_hide(var):
|
||||
return ('intent' in var and ('hide' in var['intent'] or
|
||||
('out' in var['intent'] and 'in' not in var['intent'] and
|
||||
(not l_or(isintent_inout, isintent_inplace)(var)))))
|
||||
|
||||
|
||||
def isintent_nothide(var):
|
||||
return not isintent_hide(var)
|
||||
|
||||
|
||||
def isintent_c(var):
|
||||
return 'c' in var.get('intent', [])
|
||||
|
||||
|
||||
def isintent_cache(var):
|
||||
return 'cache' in var.get('intent', [])
|
||||
|
||||
|
||||
def isintent_copy(var):
|
||||
return 'copy' in var.get('intent', [])
|
||||
|
||||
|
||||
def isintent_overwrite(var):
|
||||
return 'overwrite' in var.get('intent', [])
|
||||
|
||||
|
||||
def isintent_callback(var):
|
||||
return 'callback' in var.get('intent', [])
|
||||
|
||||
|
||||
def isintent_inplace(var):
|
||||
return 'inplace' in var.get('intent', [])
|
||||
|
||||
|
||||
def isintent_aux(var):
|
||||
return 'aux' in var.get('intent', [])
|
||||
|
||||
|
||||
def isintent_aligned4(var):
|
||||
return 'aligned4' in var.get('intent', [])
|
||||
|
||||
|
||||
def isintent_aligned8(var):
|
||||
return 'aligned8' in var.get('intent', [])
|
||||
|
||||
|
||||
def isintent_aligned16(var):
|
||||
return 'aligned16' in var.get('intent', [])
|
||||
|
||||
|
||||
isintent_dict = {isintent_in: 'INTENT_IN', isintent_inout: 'INTENT_INOUT',
|
||||
isintent_out: 'INTENT_OUT', isintent_hide: 'INTENT_HIDE',
|
||||
isintent_cache: 'INTENT_CACHE',
|
||||
isintent_c: 'INTENT_C', isoptional: 'OPTIONAL',
|
||||
isintent_inplace: 'INTENT_INPLACE',
|
||||
isintent_aligned4: 'INTENT_ALIGNED4',
|
||||
isintent_aligned8: 'INTENT_ALIGNED8',
|
||||
isintent_aligned16: 'INTENT_ALIGNED16',
|
||||
}
|
||||
|
||||
|
||||
def isprivate(var):
|
||||
return 'attrspec' in var and 'private' in var['attrspec']
|
||||
|
||||
|
||||
def isvariable(var):
|
||||
# heuristic to find public/private declarations of filtered subroutines
|
||||
if len(var) == 1 and 'attrspec' in var and \
|
||||
var['attrspec'][0] in ('public', 'private'):
|
||||
is_var = False
|
||||
else:
|
||||
is_var = True
|
||||
return is_var
|
||||
|
||||
def hasinitvalue(var):
|
||||
return '=' in var
|
||||
|
||||
|
||||
def hasinitvalueasstring(var):
|
||||
if not hasinitvalue(var):
|
||||
return 0
|
||||
return var['='][0] in ['"', "'"]
|
||||
|
||||
|
||||
def hasnote(var):
|
||||
return 'note' in var
|
||||
|
||||
|
||||
def hasresultnote(rout):
|
||||
if not isfunction(rout):
|
||||
return 0
|
||||
if 'result' in rout:
|
||||
a = rout['result']
|
||||
else:
|
||||
a = rout['name']
|
||||
if a in rout['vars']:
|
||||
return hasnote(rout['vars'][a])
|
||||
return 0
|
||||
|
||||
|
||||
def hascommon(rout):
|
||||
return 'common' in rout
|
||||
|
||||
|
||||
def containscommon(rout):
|
||||
if hascommon(rout):
|
||||
return 1
|
||||
if hasbody(rout):
|
||||
for b in rout['body']:
|
||||
if containscommon(b):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def containsmodule(block):
|
||||
if ismodule(block):
|
||||
return 1
|
||||
if not hasbody(block):
|
||||
return 0
|
||||
for b in block['body']:
|
||||
if containsmodule(b):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def hasbody(rout):
|
||||
return 'body' in rout
|
||||
|
||||
|
||||
def hascallstatement(rout):
|
||||
return getcallstatement(rout) is not None
|
||||
|
||||
|
||||
def istrue(var):
|
||||
return 1
|
||||
|
||||
|
||||
def isfalse(var):
|
||||
return 0
|
||||
|
||||
|
||||
class F2PYError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class throw_error:
|
||||
|
||||
def __init__(self, mess):
|
||||
self.mess = mess
|
||||
|
||||
def __call__(self, var):
|
||||
mess = '\n\n var = %s\n Message: %s\n' % (var, self.mess)
|
||||
raise F2PYError(mess)
|
||||
|
||||
|
||||
def l_and(*f):
|
||||
l1, l2 = 'lambda v', []
|
||||
for i in range(len(f)):
|
||||
l1 = '%s,f%d=f[%d]' % (l1, i, i)
|
||||
l2.append('f%d(v)' % (i))
|
||||
return eval('%s:%s' % (l1, ' and '.join(l2)))
|
||||
|
||||
|
||||
def l_or(*f):
|
||||
l1, l2 = 'lambda v', []
|
||||
for i in range(len(f)):
|
||||
l1 = '%s,f%d=f[%d]' % (l1, i, i)
|
||||
l2.append('f%d(v)' % (i))
|
||||
return eval('%s:%s' % (l1, ' or '.join(l2)))
|
||||
|
||||
|
||||
def l_not(f):
|
||||
return eval('lambda v,f=f:not f(v)')
|
||||
|
||||
|
||||
def isdummyroutine(rout):
|
||||
try:
|
||||
return rout['f2pyenhancements']['fortranname'] == ''
|
||||
except KeyError:
|
||||
return 0
|
||||
|
||||
|
||||
def getfortranname(rout):
|
||||
try:
|
||||
name = rout['f2pyenhancements']['fortranname']
|
||||
if name == '':
|
||||
raise KeyError
|
||||
if not name:
|
||||
errmess('Failed to use fortranname from %s\n' %
|
||||
(rout['f2pyenhancements']))
|
||||
raise KeyError
|
||||
except KeyError:
|
||||
name = rout['name']
|
||||
return name
|
||||
|
||||
|
||||
def getmultilineblock(rout, blockname, comment=1, counter=0):
|
||||
try:
|
||||
r = rout['f2pyenhancements'].get(blockname)
|
||||
except KeyError:
|
||||
return
|
||||
if not r:
|
||||
return
|
||||
if counter > 0 and isinstance(r, str):
|
||||
return
|
||||
if isinstance(r, list):
|
||||
if counter >= len(r):
|
||||
return
|
||||
r = r[counter]
|
||||
if r[:3] == "'''":
|
||||
if comment:
|
||||
r = '\t/* start ' + blockname + \
|
||||
' multiline (' + repr(counter) + ') */\n' + r[3:]
|
||||
else:
|
||||
r = r[3:]
|
||||
if r[-3:] == "'''":
|
||||
if comment:
|
||||
r = r[:-3] + '\n\t/* end multiline (' + repr(counter) + ')*/'
|
||||
else:
|
||||
r = r[:-3]
|
||||
else:
|
||||
errmess("%s multiline block should end with `'''`: %s\n"
|
||||
% (blockname, repr(r)))
|
||||
return r
|
||||
|
||||
|
||||
def getcallstatement(rout):
|
||||
return getmultilineblock(rout, 'callstatement')
|
||||
|
||||
|
||||
def getcallprotoargument(rout, cb_map={}):
|
||||
r = getmultilineblock(rout, 'callprotoargument', comment=0)
|
||||
if r:
|
||||
return r
|
||||
if hascallstatement(rout):
|
||||
outmess(
|
||||
'warning: callstatement is defined without callprotoargument\n')
|
||||
return
|
||||
from .capi_maps import getctype
|
||||
arg_types, arg_types2 = [], []
|
||||
if l_and(isstringfunction, l_not(isfunction_wrap))(rout):
|
||||
arg_types.extend(['char*', 'size_t'])
|
||||
for n in rout['args']:
|
||||
var = rout['vars'][n]
|
||||
if isintent_callback(var):
|
||||
continue
|
||||
if n in cb_map:
|
||||
ctype = cb_map[n] + '_typedef'
|
||||
else:
|
||||
ctype = getctype(var)
|
||||
if l_and(isintent_c, l_or(isscalar, iscomplex))(var):
|
||||
pass
|
||||
elif isstring(var):
|
||||
pass
|
||||
else:
|
||||
if not isattr_value(var):
|
||||
ctype = ctype + '*'
|
||||
if (isstring(var)
|
||||
or isarrayofstrings(var) # obsolete?
|
||||
or isstringarray(var)):
|
||||
arg_types2.append('size_t')
|
||||
arg_types.append(ctype)
|
||||
|
||||
proto_args = ','.join(arg_types + arg_types2)
|
||||
if not proto_args:
|
||||
proto_args = 'void'
|
||||
return proto_args
|
||||
|
||||
|
||||
def getusercode(rout):
|
||||
return getmultilineblock(rout, 'usercode')
|
||||
|
||||
|
||||
def getusercode1(rout):
|
||||
return getmultilineblock(rout, 'usercode', counter=1)
|
||||
|
||||
|
||||
def getpymethoddef(rout):
|
||||
return getmultilineblock(rout, 'pymethoddef')
|
||||
|
||||
|
||||
def getargs(rout):
|
||||
sortargs, args = [], []
|
||||
if 'args' in rout:
|
||||
args = rout['args']
|
||||
if 'sortvars' in rout:
|
||||
for a in rout['sortvars']:
|
||||
if a in args:
|
||||
sortargs.append(a)
|
||||
for a in args:
|
||||
if a not in sortargs:
|
||||
sortargs.append(a)
|
||||
else:
|
||||
sortargs = rout['args']
|
||||
return args, sortargs
|
||||
|
||||
|
||||
def getargs2(rout):
|
||||
sortargs, args = [], rout.get('args', [])
|
||||
auxvars = [a for a in rout['vars'].keys() if isintent_aux(rout['vars'][a])
|
||||
and a not in args]
|
||||
args = auxvars + args
|
||||
if 'sortvars' in rout:
|
||||
for a in rout['sortvars']:
|
||||
if a in args:
|
||||
sortargs.append(a)
|
||||
for a in args:
|
||||
if a not in sortargs:
|
||||
sortargs.append(a)
|
||||
else:
|
||||
sortargs = auxvars + rout['args']
|
||||
return args, sortargs
|
||||
|
||||
|
||||
def getrestdoc(rout):
|
||||
if 'f2pymultilines' not in rout:
|
||||
return None
|
||||
k = None
|
||||
if rout['block'] == 'python module':
|
||||
k = rout['block'], rout['name']
|
||||
return rout['f2pymultilines'].get(k, None)
|
||||
|
||||
|
||||
def gentitle(name):
|
||||
ln = (80 - len(name) - 6) // 2
|
||||
return '/*%s %s %s*/' % (ln * '*', name, ln * '*')
|
||||
|
||||
|
||||
def flatlist(lst):
|
||||
if isinstance(lst, list):
|
||||
return reduce(lambda x, y, f=flatlist: x + f(y), lst, [])
|
||||
return [lst]
|
||||
|
||||
|
||||
def stripcomma(s):
|
||||
if s and s[-1] == ',':
|
||||
return s[:-1]
|
||||
return s
|
||||
|
||||
|
||||
def replace(str, d, defaultsep=''):
|
||||
if isinstance(d, list):
|
||||
return [replace(str, _m, defaultsep) for _m in d]
|
||||
if isinstance(str, list):
|
||||
return [replace(_m, d, defaultsep) for _m in str]
|
||||
for k in 2 * list(d.keys()):
|
||||
if k == 'separatorsfor':
|
||||
continue
|
||||
if 'separatorsfor' in d and k in d['separatorsfor']:
|
||||
sep = d['separatorsfor'][k]
|
||||
else:
|
||||
sep = defaultsep
|
||||
if isinstance(d[k], list):
|
||||
str = str.replace('#%s#' % (k), sep.join(flatlist(d[k])))
|
||||
else:
|
||||
str = str.replace('#%s#' % (k), d[k])
|
||||
return str
|
||||
|
||||
|
||||
def dictappend(rd, ar):
|
||||
if isinstance(ar, list):
|
||||
for a in ar:
|
||||
rd = dictappend(rd, a)
|
||||
return rd
|
||||
for k in ar.keys():
|
||||
if k[0] == '_':
|
||||
continue
|
||||
if k in rd:
|
||||
if isinstance(rd[k], str):
|
||||
rd[k] = [rd[k]]
|
||||
if isinstance(rd[k], list):
|
||||
if isinstance(ar[k], list):
|
||||
rd[k] = rd[k] + ar[k]
|
||||
else:
|
||||
rd[k].append(ar[k])
|
||||
elif isinstance(rd[k], dict):
|
||||
if isinstance(ar[k], dict):
|
||||
if k == 'separatorsfor':
|
||||
for k1 in ar[k].keys():
|
||||
if k1 not in rd[k]:
|
||||
rd[k][k1] = ar[k][k1]
|
||||
else:
|
||||
rd[k] = dictappend(rd[k], ar[k])
|
||||
else:
|
||||
rd[k] = ar[k]
|
||||
return rd
|
||||
|
||||
|
||||
def applyrules(rules, d, var={}):
|
||||
ret = {}
|
||||
if isinstance(rules, list):
|
||||
for r in rules:
|
||||
rr = applyrules(r, d, var)
|
||||
ret = dictappend(ret, rr)
|
||||
if '_break' in rr:
|
||||
break
|
||||
return ret
|
||||
if '_check' in rules and (not rules['_check'](var)):
|
||||
return ret
|
||||
if 'need' in rules:
|
||||
res = applyrules({'needs': rules['need']}, d, var)
|
||||
if 'needs' in res:
|
||||
cfuncs.append_needs(res['needs'])
|
||||
|
||||
for k in rules.keys():
|
||||
if k == 'separatorsfor':
|
||||
ret[k] = rules[k]
|
||||
continue
|
||||
if isinstance(rules[k], str):
|
||||
ret[k] = replace(rules[k], d)
|
||||
elif isinstance(rules[k], list):
|
||||
ret[k] = []
|
||||
for i in rules[k]:
|
||||
ar = applyrules({k: i}, d, var)
|
||||
if k in ar:
|
||||
ret[k].append(ar[k])
|
||||
elif k[0] == '_':
|
||||
continue
|
||||
elif isinstance(rules[k], dict):
|
||||
ret[k] = []
|
||||
for k1 in rules[k].keys():
|
||||
if isinstance(k1, types.FunctionType) and k1(var):
|
||||
if isinstance(rules[k][k1], list):
|
||||
for i in rules[k][k1]:
|
||||
if isinstance(i, dict):
|
||||
res = applyrules({'supertext': i}, d, var)
|
||||
if 'supertext' in res:
|
||||
i = res['supertext']
|
||||
else:
|
||||
i = ''
|
||||
ret[k].append(replace(i, d))
|
||||
else:
|
||||
i = rules[k][k1]
|
||||
if isinstance(i, dict):
|
||||
res = applyrules({'supertext': i}, d)
|
||||
if 'supertext' in res:
|
||||
i = res['supertext']
|
||||
else:
|
||||
i = ''
|
||||
ret[k].append(replace(i, d))
|
||||
else:
|
||||
errmess('applyrules: ignoring rule %s.\n' % repr(rules[k]))
|
||||
if isinstance(ret[k], list):
|
||||
if len(ret[k]) == 1:
|
||||
ret[k] = ret[k][0]
|
||||
if ret[k] == []:
|
||||
del ret[k]
|
||||
return ret
|
||||
|
||||
_f2py_module_name_match = re.compile(r'\s*python\s*module\s*(?P<name>[\w_]+)',
|
||||
re.I).match
|
||||
_f2py_user_module_name_match = re.compile(r'\s*python\s*module\s*(?P<name>[\w_]*?'
|
||||
r'__user__[\w_]*)', re.I).match
|
||||
|
||||
def get_f2py_modulename(source):
|
||||
name = None
|
||||
with open(source) as f:
|
||||
for line in f:
|
||||
m = _f2py_module_name_match(line)
|
||||
if m:
|
||||
if _f2py_user_module_name_match(line): # skip *__user__* names
|
||||
continue
|
||||
name = m.group('name')
|
||||
break
|
||||
return name
|
||||
|
||||
def getuseblocks(pymod):
|
||||
all_uses = []
|
||||
for inner in pymod['body']:
|
||||
for modblock in inner['body']:
|
||||
if modblock.get('use'):
|
||||
all_uses.extend([x for x in modblock.get("use").keys() if "__" not in x])
|
||||
return all_uses
|
||||
|
||||
def process_f2cmap_dict(f2cmap_all, new_map, c2py_map, verbose = False):
|
||||
"""
|
||||
Update the Fortran-to-C type mapping dictionary with new mappings and
|
||||
return a list of successfully mapped C types.
|
||||
|
||||
This function integrates a new mapping dictionary into an existing
|
||||
Fortran-to-C type mapping dictionary. It ensures that all keys are in
|
||||
lowercase and validates new entries against a given C-to-Python mapping
|
||||
dictionary. Redefinitions and invalid entries are reported with a warning.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
f2cmap_all : dict
|
||||
The existing Fortran-to-C type mapping dictionary that will be updated.
|
||||
It should be a dictionary of dictionaries where the main keys represent
|
||||
Fortran types and the nested dictionaries map Fortran type specifiers
|
||||
to corresponding C types.
|
||||
|
||||
new_map : dict
|
||||
A dictionary containing new type mappings to be added to `f2cmap_all`.
|
||||
The structure should be similar to `f2cmap_all`, with keys representing
|
||||
Fortran types and values being dictionaries of type specifiers and their
|
||||
C type equivalents.
|
||||
|
||||
c2py_map : dict
|
||||
A dictionary used for validating the C types in `new_map`. It maps C
|
||||
types to corresponding Python types and is used to ensure that the C
|
||||
types specified in `new_map` are valid.
|
||||
|
||||
verbose : boolean
|
||||
A flag used to provide information about the types mapped
|
||||
|
||||
Returns
|
||||
-------
|
||||
tuple of (dict, list)
|
||||
The updated Fortran-to-C type mapping dictionary and a list of
|
||||
successfully mapped C types.
|
||||
"""
|
||||
f2cmap_mapped = []
|
||||
|
||||
new_map_lower = {}
|
||||
for k, d1 in new_map.items():
|
||||
d1_lower = {k1.lower(): v1 for k1, v1 in d1.items()}
|
||||
new_map_lower[k.lower()] = d1_lower
|
||||
|
||||
for k, d1 in new_map_lower.items():
|
||||
if k not in f2cmap_all:
|
||||
f2cmap_all[k] = {}
|
||||
|
||||
for k1, v1 in d1.items():
|
||||
if v1 in c2py_map:
|
||||
if k1 in f2cmap_all[k]:
|
||||
outmess(
|
||||
"\tWarning: redefinition of {'%s':{'%s':'%s'->'%s'}}\n"
|
||||
% (k, k1, f2cmap_all[k][k1], v1)
|
||||
)
|
||||
f2cmap_all[k][k1] = v1
|
||||
if verbose:
|
||||
outmess('\tMapping "%s(kind=%s)" to "%s"\n' % (k, k1, v1))
|
||||
f2cmap_mapped.append(v1)
|
||||
else:
|
||||
if verbose:
|
||||
errmess(
|
||||
"\tIgnoring map {'%s':{'%s':'%s'}}: '%s' must be in %s\n"
|
||||
% (k, k1, v1, v1, list(c2py_map.keys()))
|
||||
)
|
||||
|
||||
return f2cmap_all, f2cmap_mapped
|
821
lib/python3.13/site-packages/numpy/f2py/capi_maps.py
Normal file
821
lib/python3.13/site-packages/numpy/f2py/capi_maps.py
Normal file
@ -0,0 +1,821 @@
|
||||
"""
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
Permission to use, modify, and distribute this software is given under the
|
||||
terms of the NumPy License.
|
||||
|
||||
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
"""
|
||||
from . import __version__
|
||||
f2py_version = __version__.version
|
||||
|
||||
import copy
|
||||
import re
|
||||
import os
|
||||
from .crackfortran import markoutercomma
|
||||
from . import cb_rules
|
||||
from ._isocbind import iso_c_binding_map, isoc_c2pycode_map, iso_c2py_map
|
||||
|
||||
# The environment provided by auxfuncs.py is needed for some calls to eval.
|
||||
# As the needed functions cannot be determined by static inspection of the
|
||||
# code, it is safest to use import * pending a major refactoring of f2py.
|
||||
from .auxfuncs import *
|
||||
|
||||
__all__ = [
|
||||
'getctype', 'getstrlength', 'getarrdims', 'getpydocsign',
|
||||
'getarrdocsign', 'getinit', 'sign2map', 'routsign2map', 'modsign2map',
|
||||
'cb_sign2map', 'cb_routsign2map', 'common_sign2map', 'process_f2cmap_dict'
|
||||
]
|
||||
|
||||
|
||||
depargs = []
|
||||
lcb_map = {}
|
||||
lcb2_map = {}
|
||||
# forced casting: mainly caused by the fact that Python or Numeric
|
||||
# C/APIs do not support the corresponding C types.
|
||||
c2py_map = {'double': 'float',
|
||||
'float': 'float', # forced casting
|
||||
'long_double': 'float', # forced casting
|
||||
'char': 'int', # forced casting
|
||||
'signed_char': 'int', # forced casting
|
||||
'unsigned_char': 'int', # forced casting
|
||||
'short': 'int', # forced casting
|
||||
'unsigned_short': 'int', # forced casting
|
||||
'int': 'int', # forced casting
|
||||
'long': 'int',
|
||||
'long_long': 'long',
|
||||
'unsigned': 'int', # forced casting
|
||||
'complex_float': 'complex', # forced casting
|
||||
'complex_double': 'complex',
|
||||
'complex_long_double': 'complex', # forced casting
|
||||
'string': 'string',
|
||||
'character': 'bytes',
|
||||
}
|
||||
|
||||
c2capi_map = {'double': 'NPY_DOUBLE',
|
||||
'float': 'NPY_FLOAT',
|
||||
'long_double': 'NPY_LONGDOUBLE',
|
||||
'char': 'NPY_BYTE',
|
||||
'unsigned_char': 'NPY_UBYTE',
|
||||
'signed_char': 'NPY_BYTE',
|
||||
'short': 'NPY_SHORT',
|
||||
'unsigned_short': 'NPY_USHORT',
|
||||
'int': 'NPY_INT',
|
||||
'unsigned': 'NPY_UINT',
|
||||
'long': 'NPY_LONG',
|
||||
'unsigned_long': 'NPY_ULONG',
|
||||
'long_long': 'NPY_LONGLONG',
|
||||
'unsigned_long_long': 'NPY_ULONGLONG',
|
||||
'complex_float': 'NPY_CFLOAT',
|
||||
'complex_double': 'NPY_CDOUBLE',
|
||||
'complex_long_double': 'NPY_CDOUBLE',
|
||||
'string': 'NPY_STRING',
|
||||
'character': 'NPY_STRING'}
|
||||
|
||||
c2pycode_map = {'double': 'd',
|
||||
'float': 'f',
|
||||
'long_double': 'g',
|
||||
'char': 'b',
|
||||
'unsigned_char': 'B',
|
||||
'signed_char': 'b',
|
||||
'short': 'h',
|
||||
'unsigned_short': 'H',
|
||||
'int': 'i',
|
||||
'unsigned': 'I',
|
||||
'long': 'l',
|
||||
'unsigned_long': 'L',
|
||||
'long_long': 'q',
|
||||
'unsigned_long_long': 'Q',
|
||||
'complex_float': 'F',
|
||||
'complex_double': 'D',
|
||||
'complex_long_double': 'G',
|
||||
'string': 'S',
|
||||
'character': 'c'}
|
||||
|
||||
# https://docs.python.org/3/c-api/arg.html#building-values
|
||||
c2buildvalue_map = {'double': 'd',
|
||||
'float': 'f',
|
||||
'char': 'b',
|
||||
'signed_char': 'b',
|
||||
'short': 'h',
|
||||
'int': 'i',
|
||||
'long': 'l',
|
||||
'long_long': 'L',
|
||||
'complex_float': 'N',
|
||||
'complex_double': 'N',
|
||||
'complex_long_double': 'N',
|
||||
'string': 'y',
|
||||
'character': 'c'}
|
||||
|
||||
f2cmap_all = {'real': {'': 'float', '4': 'float', '8': 'double',
|
||||
'12': 'long_double', '16': 'long_double'},
|
||||
'integer': {'': 'int', '1': 'signed_char', '2': 'short',
|
||||
'4': 'int', '8': 'long_long',
|
||||
'-1': 'unsigned_char', '-2': 'unsigned_short',
|
||||
'-4': 'unsigned', '-8': 'unsigned_long_long'},
|
||||
'complex': {'': 'complex_float', '8': 'complex_float',
|
||||
'16': 'complex_double', '24': 'complex_long_double',
|
||||
'32': 'complex_long_double'},
|
||||
'complexkind': {'': 'complex_float', '4': 'complex_float',
|
||||
'8': 'complex_double', '12': 'complex_long_double',
|
||||
'16': 'complex_long_double'},
|
||||
'logical': {'': 'int', '1': 'char', '2': 'short', '4': 'int',
|
||||
'8': 'long_long'},
|
||||
'double complex': {'': 'complex_double'},
|
||||
'double precision': {'': 'double'},
|
||||
'byte': {'': 'char'},
|
||||
}
|
||||
|
||||
# Add ISO_C handling
|
||||
c2pycode_map.update(isoc_c2pycode_map)
|
||||
c2py_map.update(iso_c2py_map)
|
||||
f2cmap_all, _ = process_f2cmap_dict(f2cmap_all, iso_c_binding_map, c2py_map)
|
||||
# End ISO_C handling
|
||||
f2cmap_default = copy.deepcopy(f2cmap_all)
|
||||
|
||||
f2cmap_mapped = []
|
||||
|
||||
def load_f2cmap_file(f2cmap_file):
|
||||
global f2cmap_all, f2cmap_mapped
|
||||
|
||||
f2cmap_all = copy.deepcopy(f2cmap_default)
|
||||
|
||||
if f2cmap_file is None:
|
||||
# Default value
|
||||
f2cmap_file = '.f2py_f2cmap'
|
||||
if not os.path.isfile(f2cmap_file):
|
||||
return
|
||||
|
||||
# User defined additions to f2cmap_all.
|
||||
# f2cmap_file must contain a dictionary of dictionaries, only. For
|
||||
# example, {'real':{'low':'float'}} means that Fortran 'real(low)' is
|
||||
# interpreted as C 'float'. This feature is useful for F90/95 users if
|
||||
# they use PARAMETERS in type specifications.
|
||||
try:
|
||||
outmess('Reading f2cmap from {!r} ...\n'.format(f2cmap_file))
|
||||
with open(f2cmap_file) as f:
|
||||
d = eval(f.read().lower(), {}, {})
|
||||
f2cmap_all, f2cmap_mapped = process_f2cmap_dict(f2cmap_all, d, c2py_map, True)
|
||||
outmess('Successfully applied user defined f2cmap changes\n')
|
||||
except Exception as msg:
|
||||
errmess('Failed to apply user defined f2cmap changes: %s. Skipping.\n' % (msg))
|
||||
|
||||
|
||||
cformat_map = {'double': '%g',
|
||||
'float': '%g',
|
||||
'long_double': '%Lg',
|
||||
'char': '%d',
|
||||
'signed_char': '%d',
|
||||
'unsigned_char': '%hhu',
|
||||
'short': '%hd',
|
||||
'unsigned_short': '%hu',
|
||||
'int': '%d',
|
||||
'unsigned': '%u',
|
||||
'long': '%ld',
|
||||
'unsigned_long': '%lu',
|
||||
'long_long': '%ld',
|
||||
'complex_float': '(%g,%g)',
|
||||
'complex_double': '(%g,%g)',
|
||||
'complex_long_double': '(%Lg,%Lg)',
|
||||
'string': '\\"%s\\"',
|
||||
'character': "'%c'",
|
||||
}
|
||||
|
||||
# Auxiliary functions
|
||||
|
||||
|
||||
def getctype(var):
|
||||
"""
|
||||
Determines C type
|
||||
"""
|
||||
ctype = 'void'
|
||||
if isfunction(var):
|
||||
if 'result' in var:
|
||||
a = var['result']
|
||||
else:
|
||||
a = var['name']
|
||||
if a in var['vars']:
|
||||
return getctype(var['vars'][a])
|
||||
else:
|
||||
errmess('getctype: function %s has no return value?!\n' % a)
|
||||
elif issubroutine(var):
|
||||
return ctype
|
||||
elif ischaracter_or_characterarray(var):
|
||||
return 'character'
|
||||
elif isstring_or_stringarray(var):
|
||||
return 'string'
|
||||
elif 'typespec' in var and var['typespec'].lower() in f2cmap_all:
|
||||
typespec = var['typespec'].lower()
|
||||
f2cmap = f2cmap_all[typespec]
|
||||
ctype = f2cmap[''] # default type
|
||||
if 'kindselector' in var:
|
||||
if '*' in var['kindselector']:
|
||||
try:
|
||||
ctype = f2cmap[var['kindselector']['*']]
|
||||
except KeyError:
|
||||
errmess('getctype: "%s %s %s" not supported.\n' %
|
||||
(var['typespec'], '*', var['kindselector']['*']))
|
||||
elif 'kind' in var['kindselector']:
|
||||
if typespec + 'kind' in f2cmap_all:
|
||||
f2cmap = f2cmap_all[typespec + 'kind']
|
||||
try:
|
||||
ctype = f2cmap[var['kindselector']['kind']]
|
||||
except KeyError:
|
||||
if typespec in f2cmap_all:
|
||||
f2cmap = f2cmap_all[typespec]
|
||||
try:
|
||||
ctype = f2cmap[str(var['kindselector']['kind'])]
|
||||
except KeyError:
|
||||
errmess('getctype: "%s(kind=%s)" is mapped to C "%s" (to override define dict(%s = dict(%s="<C typespec>")) in %s/.f2py_f2cmap file).\n'
|
||||
% (typespec, var['kindselector']['kind'], ctype,
|
||||
typespec, var['kindselector']['kind'], os.getcwd()))
|
||||
else:
|
||||
if not isexternal(var):
|
||||
errmess('getctype: No C-type found in "%s", assuming void.\n' % var)
|
||||
return ctype
|
||||
|
||||
|
||||
def f2cexpr(expr):
|
||||
"""Rewrite Fortran expression as f2py supported C expression.
|
||||
|
||||
Due to the lack of a proper expression parser in f2py, this
|
||||
function uses a heuristic approach that assumes that Fortran
|
||||
arithmetic expressions are valid C arithmetic expressions when
|
||||
mapping Fortran function calls to the corresponding C function/CPP
|
||||
macros calls.
|
||||
|
||||
"""
|
||||
# TODO: support Fortran `len` function with optional kind parameter
|
||||
expr = re.sub(r'\blen\b', 'f2py_slen', expr)
|
||||
return expr
|
||||
|
||||
|
||||
def getstrlength(var):
|
||||
if isstringfunction(var):
|
||||
if 'result' in var:
|
||||
a = var['result']
|
||||
else:
|
||||
a = var['name']
|
||||
if a in var['vars']:
|
||||
return getstrlength(var['vars'][a])
|
||||
else:
|
||||
errmess('getstrlength: function %s has no return value?!\n' % a)
|
||||
if not isstring(var):
|
||||
errmess(
|
||||
'getstrlength: expected a signature of a string but got: %s\n' % (repr(var)))
|
||||
len = '1'
|
||||
if 'charselector' in var:
|
||||
a = var['charselector']
|
||||
if '*' in a:
|
||||
len = a['*']
|
||||
elif 'len' in a:
|
||||
len = f2cexpr(a['len'])
|
||||
if re.match(r'\(\s*(\*|:)\s*\)', len) or re.match(r'(\*|:)', len):
|
||||
if isintent_hide(var):
|
||||
errmess('getstrlength:intent(hide): expected a string with defined length but got: %s\n' % (
|
||||
repr(var)))
|
||||
len = '-1'
|
||||
return len
|
||||
|
||||
|
||||
def getarrdims(a, var, verbose=0):
|
||||
ret = {}
|
||||
if isstring(var) and not isarray(var):
|
||||
ret['size'] = getstrlength(var)
|
||||
ret['rank'] = '0'
|
||||
ret['dims'] = ''
|
||||
elif isscalar(var):
|
||||
ret['size'] = '1'
|
||||
ret['rank'] = '0'
|
||||
ret['dims'] = ''
|
||||
elif isarray(var):
|
||||
dim = copy.copy(var['dimension'])
|
||||
ret['size'] = '*'.join(dim)
|
||||
try:
|
||||
ret['size'] = repr(eval(ret['size']))
|
||||
except Exception:
|
||||
pass
|
||||
ret['dims'] = ','.join(dim)
|
||||
ret['rank'] = repr(len(dim))
|
||||
ret['rank*[-1]'] = repr(len(dim) * [-1])[1:-1]
|
||||
for i in range(len(dim)): # solve dim for dependencies
|
||||
v = []
|
||||
if dim[i] in depargs:
|
||||
v = [dim[i]]
|
||||
else:
|
||||
for va in depargs:
|
||||
if re.match(r'.*?\b%s\b.*' % va, dim[i]):
|
||||
v.append(va)
|
||||
for va in v:
|
||||
if depargs.index(va) > depargs.index(a):
|
||||
dim[i] = '*'
|
||||
break
|
||||
ret['setdims'], i = '', -1
|
||||
for d in dim:
|
||||
i = i + 1
|
||||
if d not in ['*', ':', '(*)', '(:)']:
|
||||
ret['setdims'] = '%s#varname#_Dims[%d]=%s,' % (
|
||||
ret['setdims'], i, d)
|
||||
if ret['setdims']:
|
||||
ret['setdims'] = ret['setdims'][:-1]
|
||||
ret['cbsetdims'], i = '', -1
|
||||
for d in var['dimension']:
|
||||
i = i + 1
|
||||
if d not in ['*', ':', '(*)', '(:)']:
|
||||
ret['cbsetdims'] = '%s#varname#_Dims[%d]=%s,' % (
|
||||
ret['cbsetdims'], i, d)
|
||||
elif isintent_in(var):
|
||||
outmess('getarrdims:warning: assumed shape array, using 0 instead of %r\n'
|
||||
% (d))
|
||||
ret['cbsetdims'] = '%s#varname#_Dims[%d]=%s,' % (
|
||||
ret['cbsetdims'], i, 0)
|
||||
elif verbose:
|
||||
errmess(
|
||||
'getarrdims: If in call-back function: array argument %s must have bounded dimensions: got %s\n' % (repr(a), repr(d)))
|
||||
if ret['cbsetdims']:
|
||||
ret['cbsetdims'] = ret['cbsetdims'][:-1]
|
||||
# if not isintent_c(var):
|
||||
# var['dimension'].reverse()
|
||||
return ret
|
||||
|
||||
|
||||
def getpydocsign(a, var):
|
||||
global lcb_map
|
||||
if isfunction(var):
|
||||
if 'result' in var:
|
||||
af = var['result']
|
||||
else:
|
||||
af = var['name']
|
||||
if af in var['vars']:
|
||||
return getpydocsign(af, var['vars'][af])
|
||||
else:
|
||||
errmess('getctype: function %s has no return value?!\n' % af)
|
||||
return '', ''
|
||||
sig, sigout = a, a
|
||||
opt = ''
|
||||
if isintent_in(var):
|
||||
opt = 'input'
|
||||
elif isintent_inout(var):
|
||||
opt = 'in/output'
|
||||
out_a = a
|
||||
if isintent_out(var):
|
||||
for k in var['intent']:
|
||||
if k[:4] == 'out=':
|
||||
out_a = k[4:]
|
||||
break
|
||||
init = ''
|
||||
ctype = getctype(var)
|
||||
|
||||
if hasinitvalue(var):
|
||||
init, showinit = getinit(a, var)
|
||||
init = ', optional\\n Default: %s' % showinit
|
||||
if isscalar(var):
|
||||
if isintent_inout(var):
|
||||
sig = '%s : %s rank-0 array(%s,\'%s\')%s' % (a, opt, c2py_map[ctype],
|
||||
c2pycode_map[ctype], init)
|
||||
else:
|
||||
sig = '%s : %s %s%s' % (a, opt, c2py_map[ctype], init)
|
||||
sigout = '%s : %s' % (out_a, c2py_map[ctype])
|
||||
elif isstring(var):
|
||||
if isintent_inout(var):
|
||||
sig = '%s : %s rank-0 array(string(len=%s),\'c\')%s' % (
|
||||
a, opt, getstrlength(var), init)
|
||||
else:
|
||||
sig = '%s : %s string(len=%s)%s' % (
|
||||
a, opt, getstrlength(var), init)
|
||||
sigout = '%s : string(len=%s)' % (out_a, getstrlength(var))
|
||||
elif isarray(var):
|
||||
dim = var['dimension']
|
||||
rank = repr(len(dim))
|
||||
sig = '%s : %s rank-%s array(\'%s\') with bounds (%s)%s' % (a, opt, rank,
|
||||
c2pycode_map[
|
||||
ctype],
|
||||
','.join(dim), init)
|
||||
if a == out_a:
|
||||
sigout = '%s : rank-%s array(\'%s\') with bounds (%s)'\
|
||||
% (a, rank, c2pycode_map[ctype], ','.join(dim))
|
||||
else:
|
||||
sigout = '%s : rank-%s array(\'%s\') with bounds (%s) and %s storage'\
|
||||
% (out_a, rank, c2pycode_map[ctype], ','.join(dim), a)
|
||||
elif isexternal(var):
|
||||
ua = ''
|
||||
if a in lcb_map and lcb_map[a] in lcb2_map and 'argname' in lcb2_map[lcb_map[a]]:
|
||||
ua = lcb2_map[lcb_map[a]]['argname']
|
||||
if not ua == a:
|
||||
ua = ' => %s' % ua
|
||||
else:
|
||||
ua = ''
|
||||
sig = '%s : call-back function%s' % (a, ua)
|
||||
sigout = sig
|
||||
else:
|
||||
errmess(
|
||||
'getpydocsign: Could not resolve docsignature for "%s".\n' % a)
|
||||
return sig, sigout
|
||||
|
||||
|
||||
def getarrdocsign(a, var):
|
||||
ctype = getctype(var)
|
||||
if isstring(var) and (not isarray(var)):
|
||||
sig = '%s : rank-0 array(string(len=%s),\'c\')' % (a,
|
||||
getstrlength(var))
|
||||
elif isscalar(var):
|
||||
sig = '%s : rank-0 array(%s,\'%s\')' % (a, c2py_map[ctype],
|
||||
c2pycode_map[ctype],)
|
||||
elif isarray(var):
|
||||
dim = var['dimension']
|
||||
rank = repr(len(dim))
|
||||
sig = '%s : rank-%s array(\'%s\') with bounds (%s)' % (a, rank,
|
||||
c2pycode_map[
|
||||
ctype],
|
||||
','.join(dim))
|
||||
return sig
|
||||
|
||||
|
||||
def getinit(a, var):
|
||||
if isstring(var):
|
||||
init, showinit = '""', "''"
|
||||
else:
|
||||
init, showinit = '', ''
|
||||
if hasinitvalue(var):
|
||||
init = var['=']
|
||||
showinit = init
|
||||
if iscomplex(var) or iscomplexarray(var):
|
||||
ret = {}
|
||||
|
||||
try:
|
||||
v = var["="]
|
||||
if ',' in v:
|
||||
ret['init.r'], ret['init.i'] = markoutercomma(
|
||||
v[1:-1]).split('@,@')
|
||||
else:
|
||||
v = eval(v, {}, {})
|
||||
ret['init.r'], ret['init.i'] = str(v.real), str(v.imag)
|
||||
except Exception:
|
||||
raise ValueError(
|
||||
'getinit: expected complex number `(r,i)\' but got `%s\' as initial value of %r.' % (init, a))
|
||||
if isarray(var):
|
||||
init = '(capi_c.r=%s,capi_c.i=%s,capi_c)' % (
|
||||
ret['init.r'], ret['init.i'])
|
||||
elif isstring(var):
|
||||
if not init:
|
||||
init, showinit = '""', "''"
|
||||
if init[0] == "'":
|
||||
init = '"%s"' % (init[1:-1].replace('"', '\\"'))
|
||||
if init[0] == '"':
|
||||
showinit = "'%s'" % (init[1:-1])
|
||||
return init, showinit
|
||||
|
||||
|
||||
def get_elsize(var):
|
||||
if isstring(var) or isstringarray(var):
|
||||
elsize = getstrlength(var)
|
||||
# override with user-specified length when available:
|
||||
elsize = var['charselector'].get('f2py_len', elsize)
|
||||
return elsize
|
||||
if ischaracter(var) or ischaracterarray(var):
|
||||
return '1'
|
||||
# for numerical types, PyArray_New* functions ignore specified
|
||||
# elsize, so we just return 1 and let elsize be determined at
|
||||
# runtime, see fortranobject.c
|
||||
return '1'
|
||||
|
||||
|
||||
def sign2map(a, var):
|
||||
"""
|
||||
varname,ctype,atype
|
||||
init,init.r,init.i,pytype
|
||||
vardebuginfo,vardebugshowvalue,varshowvalue
|
||||
varrformat
|
||||
|
||||
intent
|
||||
"""
|
||||
out_a = a
|
||||
if isintent_out(var):
|
||||
for k in var['intent']:
|
||||
if k[:4] == 'out=':
|
||||
out_a = k[4:]
|
||||
break
|
||||
ret = {'varname': a, 'outvarname': out_a, 'ctype': getctype(var)}
|
||||
intent_flags = []
|
||||
for f, s in isintent_dict.items():
|
||||
if f(var):
|
||||
intent_flags.append('F2PY_%s' % s)
|
||||
if intent_flags:
|
||||
# TODO: Evaluate intent_flags here.
|
||||
ret['intent'] = '|'.join(intent_flags)
|
||||
else:
|
||||
ret['intent'] = 'F2PY_INTENT_IN'
|
||||
if isarray(var):
|
||||
ret['varrformat'] = 'N'
|
||||
elif ret['ctype'] in c2buildvalue_map:
|
||||
ret['varrformat'] = c2buildvalue_map[ret['ctype']]
|
||||
else:
|
||||
ret['varrformat'] = 'O'
|
||||
ret['init'], ret['showinit'] = getinit(a, var)
|
||||
if hasinitvalue(var) and iscomplex(var) and not isarray(var):
|
||||
ret['init.r'], ret['init.i'] = markoutercomma(
|
||||
ret['init'][1:-1]).split('@,@')
|
||||
if isexternal(var):
|
||||
ret['cbnamekey'] = a
|
||||
if a in lcb_map:
|
||||
ret['cbname'] = lcb_map[a]
|
||||
ret['maxnofargs'] = lcb2_map[lcb_map[a]]['maxnofargs']
|
||||
ret['nofoptargs'] = lcb2_map[lcb_map[a]]['nofoptargs']
|
||||
ret['cbdocstr'] = lcb2_map[lcb_map[a]]['docstr']
|
||||
ret['cblatexdocstr'] = lcb2_map[lcb_map[a]]['latexdocstr']
|
||||
else:
|
||||
ret['cbname'] = a
|
||||
errmess('sign2map: Confused: external %s is not in lcb_map%s.\n' % (
|
||||
a, list(lcb_map.keys())))
|
||||
if isstring(var):
|
||||
ret['length'] = getstrlength(var)
|
||||
if isarray(var):
|
||||
ret = dictappend(ret, getarrdims(a, var))
|
||||
dim = copy.copy(var['dimension'])
|
||||
if ret['ctype'] in c2capi_map:
|
||||
ret['atype'] = c2capi_map[ret['ctype']]
|
||||
ret['elsize'] = get_elsize(var)
|
||||
# Debug info
|
||||
if debugcapi(var):
|
||||
il = [isintent_in, 'input', isintent_out, 'output',
|
||||
isintent_inout, 'inoutput', isrequired, 'required',
|
||||
isoptional, 'optional', isintent_hide, 'hidden',
|
||||
iscomplex, 'complex scalar',
|
||||
l_and(isscalar, l_not(iscomplex)), 'scalar',
|
||||
isstring, 'string', isarray, 'array',
|
||||
iscomplexarray, 'complex array', isstringarray, 'string array',
|
||||
iscomplexfunction, 'complex function',
|
||||
l_and(isfunction, l_not(iscomplexfunction)), 'function',
|
||||
isexternal, 'callback',
|
||||
isintent_callback, 'callback',
|
||||
isintent_aux, 'auxiliary',
|
||||
]
|
||||
rl = []
|
||||
for i in range(0, len(il), 2):
|
||||
if il[i](var):
|
||||
rl.append(il[i + 1])
|
||||
if isstring(var):
|
||||
rl.append('slen(%s)=%s' % (a, ret['length']))
|
||||
if isarray(var):
|
||||
ddim = ','.join(
|
||||
map(lambda x, y: '%s|%s' % (x, y), var['dimension'], dim))
|
||||
rl.append('dims(%s)' % ddim)
|
||||
if isexternal(var):
|
||||
ret['vardebuginfo'] = 'debug-capi:%s=>%s:%s' % (
|
||||
a, ret['cbname'], ','.join(rl))
|
||||
else:
|
||||
ret['vardebuginfo'] = 'debug-capi:%s %s=%s:%s' % (
|
||||
ret['ctype'], a, ret['showinit'], ','.join(rl))
|
||||
if isscalar(var):
|
||||
if ret['ctype'] in cformat_map:
|
||||
ret['vardebugshowvalue'] = 'debug-capi:%s=%s' % (
|
||||
a, cformat_map[ret['ctype']])
|
||||
if isstring(var):
|
||||
ret['vardebugshowvalue'] = 'debug-capi:slen(%s)=%%d %s=\\"%%s\\"' % (
|
||||
a, a)
|
||||
if isexternal(var):
|
||||
ret['vardebugshowvalue'] = 'debug-capi:%s=%%p' % (a)
|
||||
if ret['ctype'] in cformat_map:
|
||||
ret['varshowvalue'] = '#name#:%s=%s' % (a, cformat_map[ret['ctype']])
|
||||
ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
|
||||
if isstring(var):
|
||||
ret['varshowvalue'] = '#name#:slen(%s)=%%d %s=\\"%%s\\"' % (a, a)
|
||||
ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
|
||||
if hasnote(var):
|
||||
ret['note'] = var['note']
|
||||
return ret
|
||||
|
||||
|
||||
def routsign2map(rout):
|
||||
"""
|
||||
name,NAME,begintitle,endtitle
|
||||
rname,ctype,rformat
|
||||
routdebugshowvalue
|
||||
"""
|
||||
global lcb_map
|
||||
name = rout['name']
|
||||
fname = getfortranname(rout)
|
||||
ret = {'name': name,
|
||||
'texname': name.replace('_', '\\_'),
|
||||
'name_lower': name.lower(),
|
||||
'NAME': name.upper(),
|
||||
'begintitle': gentitle(name),
|
||||
'endtitle': gentitle('end of %s' % name),
|
||||
'fortranname': fname,
|
||||
'FORTRANNAME': fname.upper(),
|
||||
'callstatement': getcallstatement(rout) or '',
|
||||
'usercode': getusercode(rout) or '',
|
||||
'usercode1': getusercode1(rout) or '',
|
||||
}
|
||||
if '_' in fname:
|
||||
ret['F_FUNC'] = 'F_FUNC_US'
|
||||
else:
|
||||
ret['F_FUNC'] = 'F_FUNC'
|
||||
if '_' in name:
|
||||
ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC_US'
|
||||
else:
|
||||
ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC'
|
||||
lcb_map = {}
|
||||
if 'use' in rout:
|
||||
for u in rout['use'].keys():
|
||||
if u in cb_rules.cb_map:
|
||||
for un in cb_rules.cb_map[u]:
|
||||
ln = un[0]
|
||||
if 'map' in rout['use'][u]:
|
||||
for k in rout['use'][u]['map'].keys():
|
||||
if rout['use'][u]['map'][k] == un[0]:
|
||||
ln = k
|
||||
break
|
||||
lcb_map[ln] = un[1]
|
||||
elif 'externals' in rout and rout['externals']:
|
||||
errmess('routsign2map: Confused: function %s has externals %s but no "use" statement.\n' % (
|
||||
ret['name'], repr(rout['externals'])))
|
||||
ret['callprotoargument'] = getcallprotoargument(rout, lcb_map) or ''
|
||||
if isfunction(rout):
|
||||
if 'result' in rout:
|
||||
a = rout['result']
|
||||
else:
|
||||
a = rout['name']
|
||||
ret['rname'] = a
|
||||
ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, rout)
|
||||
ret['ctype'] = getctype(rout['vars'][a])
|
||||
if hasresultnote(rout):
|
||||
ret['resultnote'] = rout['vars'][a]['note']
|
||||
rout['vars'][a]['note'] = ['See elsewhere.']
|
||||
if ret['ctype'] in c2buildvalue_map:
|
||||
ret['rformat'] = c2buildvalue_map[ret['ctype']]
|
||||
else:
|
||||
ret['rformat'] = 'O'
|
||||
errmess('routsign2map: no c2buildvalue key for type %s\n' %
|
||||
(repr(ret['ctype'])))
|
||||
if debugcapi(rout):
|
||||
if ret['ctype'] in cformat_map:
|
||||
ret['routdebugshowvalue'] = 'debug-capi:%s=%s' % (
|
||||
a, cformat_map[ret['ctype']])
|
||||
if isstringfunction(rout):
|
||||
ret['routdebugshowvalue'] = 'debug-capi:slen(%s)=%%d %s=\\"%%s\\"' % (
|
||||
a, a)
|
||||
if isstringfunction(rout):
|
||||
ret['rlength'] = getstrlength(rout['vars'][a])
|
||||
if ret['rlength'] == '-1':
|
||||
errmess('routsign2map: expected explicit specification of the length of the string returned by the fortran function %s; taking 10.\n' % (
|
||||
repr(rout['name'])))
|
||||
ret['rlength'] = '10'
|
||||
if hasnote(rout):
|
||||
ret['note'] = rout['note']
|
||||
rout['note'] = ['See elsewhere.']
|
||||
return ret
|
||||
|
||||
|
||||
def modsign2map(m):
|
||||
"""
|
||||
modulename
|
||||
"""
|
||||
if ismodule(m):
|
||||
ret = {'f90modulename': m['name'],
|
||||
'F90MODULENAME': m['name'].upper(),
|
||||
'texf90modulename': m['name'].replace('_', '\\_')}
|
||||
else:
|
||||
ret = {'modulename': m['name'],
|
||||
'MODULENAME': m['name'].upper(),
|
||||
'texmodulename': m['name'].replace('_', '\\_')}
|
||||
ret['restdoc'] = getrestdoc(m) or []
|
||||
if hasnote(m):
|
||||
ret['note'] = m['note']
|
||||
ret['usercode'] = getusercode(m) or ''
|
||||
ret['usercode1'] = getusercode1(m) or ''
|
||||
if m['body']:
|
||||
ret['interface_usercode'] = getusercode(m['body'][0]) or ''
|
||||
else:
|
||||
ret['interface_usercode'] = ''
|
||||
ret['pymethoddef'] = getpymethoddef(m) or ''
|
||||
if 'gil_used' in m:
|
||||
ret['gil_used'] = m['gil_used']
|
||||
if 'coutput' in m:
|
||||
ret['coutput'] = m['coutput']
|
||||
if 'f2py_wrapper_output' in m:
|
||||
ret['f2py_wrapper_output'] = m['f2py_wrapper_output']
|
||||
return ret
|
||||
|
||||
|
||||
def cb_sign2map(a, var, index=None):
|
||||
ret = {'varname': a}
|
||||
ret['varname_i'] = ret['varname']
|
||||
ret['ctype'] = getctype(var)
|
||||
if ret['ctype'] in c2capi_map:
|
||||
ret['atype'] = c2capi_map[ret['ctype']]
|
||||
ret['elsize'] = get_elsize(var)
|
||||
if ret['ctype'] in cformat_map:
|
||||
ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
|
||||
if isarray(var):
|
||||
ret = dictappend(ret, getarrdims(a, var))
|
||||
ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
|
||||
if hasnote(var):
|
||||
ret['note'] = var['note']
|
||||
var['note'] = ['See elsewhere.']
|
||||
return ret
|
||||
|
||||
|
||||
def cb_routsign2map(rout, um):
|
||||
"""
|
||||
name,begintitle,endtitle,argname
|
||||
ctype,rctype,maxnofargs,nofoptargs,returncptr
|
||||
"""
|
||||
ret = {'name': 'cb_%s_in_%s' % (rout['name'], um),
|
||||
'returncptr': ''}
|
||||
if isintent_callback(rout):
|
||||
if '_' in rout['name']:
|
||||
F_FUNC = 'F_FUNC_US'
|
||||
else:
|
||||
F_FUNC = 'F_FUNC'
|
||||
ret['callbackname'] = '%s(%s,%s)' \
|
||||
% (F_FUNC,
|
||||
rout['name'].lower(),
|
||||
rout['name'].upper(),
|
||||
)
|
||||
ret['static'] = 'extern'
|
||||
else:
|
||||
ret['callbackname'] = ret['name']
|
||||
ret['static'] = 'static'
|
||||
ret['argname'] = rout['name']
|
||||
ret['begintitle'] = gentitle(ret['name'])
|
||||
ret['endtitle'] = gentitle('end of %s' % ret['name'])
|
||||
ret['ctype'] = getctype(rout)
|
||||
ret['rctype'] = 'void'
|
||||
if ret['ctype'] == 'string':
|
||||
ret['rctype'] = 'void'
|
||||
else:
|
||||
ret['rctype'] = ret['ctype']
|
||||
if ret['rctype'] != 'void':
|
||||
if iscomplexfunction(rout):
|
||||
ret['returncptr'] = """
|
||||
#ifdef F2PY_CB_RETURNCOMPLEX
|
||||
return_value=
|
||||
#endif
|
||||
"""
|
||||
else:
|
||||
ret['returncptr'] = 'return_value='
|
||||
if ret['ctype'] in cformat_map:
|
||||
ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
|
||||
if isstringfunction(rout):
|
||||
ret['strlength'] = getstrlength(rout)
|
||||
if isfunction(rout):
|
||||
if 'result' in rout:
|
||||
a = rout['result']
|
||||
else:
|
||||
a = rout['name']
|
||||
if hasnote(rout['vars'][a]):
|
||||
ret['note'] = rout['vars'][a]['note']
|
||||
rout['vars'][a]['note'] = ['See elsewhere.']
|
||||
ret['rname'] = a
|
||||
ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, rout)
|
||||
if iscomplexfunction(rout):
|
||||
ret['rctype'] = """
|
||||
#ifdef F2PY_CB_RETURNCOMPLEX
|
||||
#ctype#
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
"""
|
||||
else:
|
||||
if hasnote(rout):
|
||||
ret['note'] = rout['note']
|
||||
rout['note'] = ['See elsewhere.']
|
||||
nofargs = 0
|
||||
nofoptargs = 0
|
||||
if 'args' in rout and 'vars' in rout:
|
||||
for a in rout['args']:
|
||||
var = rout['vars'][a]
|
||||
if l_or(isintent_in, isintent_inout)(var):
|
||||
nofargs = nofargs + 1
|
||||
if isoptional(var):
|
||||
nofoptargs = nofoptargs + 1
|
||||
ret['maxnofargs'] = repr(nofargs)
|
||||
ret['nofoptargs'] = repr(nofoptargs)
|
||||
if hasnote(rout) and isfunction(rout) and 'result' in rout:
|
||||
ret['routnote'] = rout['note']
|
||||
rout['note'] = ['See elsewhere.']
|
||||
return ret
|
||||
|
||||
|
||||
def common_sign2map(a, var): # obsolute
|
||||
ret = {'varname': a, 'ctype': getctype(var)}
|
||||
if isstringarray(var):
|
||||
ret['ctype'] = 'char'
|
||||
if ret['ctype'] in c2capi_map:
|
||||
ret['atype'] = c2capi_map[ret['ctype']]
|
||||
ret['elsize'] = get_elsize(var)
|
||||
if ret['ctype'] in cformat_map:
|
||||
ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
|
||||
if isarray(var):
|
||||
ret = dictappend(ret, getarrdims(a, var))
|
||||
elif isstring(var):
|
||||
ret['size'] = getstrlength(var)
|
||||
ret['rank'] = '1'
|
||||
ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
|
||||
if hasnote(var):
|
||||
ret['note'] = var['note']
|
||||
var['note'] = ['See elsewhere.']
|
||||
# for strings this returns 0-rank but actually is 1-rank
|
||||
ret['arrdocstr'] = getarrdocsign(a, var)
|
||||
return ret
|
644
lib/python3.13/site-packages/numpy/f2py/cb_rules.py
Normal file
644
lib/python3.13/site-packages/numpy/f2py/cb_rules.py
Normal file
@ -0,0 +1,644 @@
|
||||
"""
|
||||
Build call-back mechanism for f2py2e.
|
||||
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
Permission to use, modify, and distribute this software is given under the
|
||||
terms of the NumPy License.
|
||||
|
||||
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
"""
|
||||
from . import __version__
|
||||
from .auxfuncs import (
|
||||
applyrules, debugcapi, dictappend, errmess, getargs, hasnote, isarray,
|
||||
iscomplex, iscomplexarray, iscomplexfunction, isfunction, isintent_c,
|
||||
isintent_hide, isintent_in, isintent_inout, isintent_nothide,
|
||||
isintent_out, isoptional, isrequired, isscalar, isstring,
|
||||
isstringfunction, issubroutine, l_and, l_not, l_or, outmess, replace,
|
||||
stripcomma, throw_error
|
||||
)
|
||||
from . import cfuncs
|
||||
|
||||
f2py_version = __version__.version
|
||||
|
||||
|
||||
################## Rules for callback function ##############
|
||||
|
||||
cb_routine_rules = {
|
||||
'cbtypedefs': 'typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);',
|
||||
'body': """
|
||||
#begintitle#
|
||||
typedef struct {
|
||||
PyObject *capi;
|
||||
PyTupleObject *args_capi;
|
||||
int nofargs;
|
||||
jmp_buf jmpbuf;
|
||||
} #name#_t;
|
||||
|
||||
#if defined(F2PY_THREAD_LOCAL_DECL) && !defined(F2PY_USE_PYTHON_TLS)
|
||||
|
||||
static F2PY_THREAD_LOCAL_DECL #name#_t *_active_#name# = NULL;
|
||||
|
||||
static #name#_t *swap_active_#name#(#name#_t *ptr) {
|
||||
#name#_t *prev = _active_#name#;
|
||||
_active_#name# = ptr;
|
||||
return prev;
|
||||
}
|
||||
|
||||
static #name#_t *get_active_#name#(void) {
|
||||
return _active_#name#;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static #name#_t *swap_active_#name#(#name#_t *ptr) {
|
||||
char *key = "__f2py_cb_#name#";
|
||||
return (#name#_t *)F2PySwapThreadLocalCallbackPtr(key, ptr);
|
||||
}
|
||||
|
||||
static #name#_t *get_active_#name#(void) {
|
||||
char *key = "__f2py_cb_#name#";
|
||||
return (#name#_t *)F2PyGetThreadLocalCallbackPtr(key);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);*/
|
||||
#static# #rctype# #callbackname# (#optargs##args##strarglens##noargs#) {
|
||||
#name#_t cb_local = { NULL, NULL, 0 };
|
||||
#name#_t *cb = NULL;
|
||||
PyTupleObject *capi_arglist = NULL;
|
||||
PyObject *capi_return = NULL;
|
||||
PyObject *capi_tmp = NULL;
|
||||
PyObject *capi_arglist_list = NULL;
|
||||
int capi_j,capi_i = 0;
|
||||
int capi_longjmp_ok = 1;
|
||||
#decl#
|
||||
#ifdef F2PY_REPORT_ATEXIT
|
||||
f2py_cb_start_clock();
|
||||
#endif
|
||||
cb = get_active_#name#();
|
||||
if (cb == NULL) {
|
||||
capi_longjmp_ok = 0;
|
||||
cb = &cb_local;
|
||||
}
|
||||
capi_arglist = cb->args_capi;
|
||||
CFUNCSMESS(\"cb:Call-back function #name# (maxnofargs=#maxnofargs#(-#nofoptargs#))\\n\");
|
||||
CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi);
|
||||
if (cb->capi==NULL) {
|
||||
capi_longjmp_ok = 0;
|
||||
cb->capi = PyObject_GetAttrString(#modulename#_module,\"#argname#\");
|
||||
CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi);
|
||||
}
|
||||
if (cb->capi==NULL) {
|
||||
PyErr_SetString(#modulename#_error,\"cb: Callback #argname# not defined (as an argument or module #modulename# attribute).\\n\");
|
||||
goto capi_fail;
|
||||
}
|
||||
if (F2PyCapsule_Check(cb->capi)) {
|
||||
#name#_typedef #name#_cptr;
|
||||
#name#_cptr = F2PyCapsule_AsVoidPtr(cb->capi);
|
||||
#returncptr#(*#name#_cptr)(#optargs_nm##args_nm##strarglens_nm#);
|
||||
#return#
|
||||
}
|
||||
if (capi_arglist==NULL) {
|
||||
capi_longjmp_ok = 0;
|
||||
capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#argname#_extra_args\");
|
||||
if (capi_tmp) {
|
||||
capi_arglist = (PyTupleObject *)PySequence_Tuple(capi_tmp);
|
||||
Py_DECREF(capi_tmp);
|
||||
if (capi_arglist==NULL) {
|
||||
PyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#argname#_extra_args to tuple.\\n\");
|
||||
goto capi_fail;
|
||||
}
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
capi_arglist = (PyTupleObject *)Py_BuildValue(\"()\");
|
||||
}
|
||||
}
|
||||
if (capi_arglist == NULL) {
|
||||
PyErr_SetString(#modulename#_error,\"Callback #argname# argument list is not set.\\n\");
|
||||
goto capi_fail;
|
||||
}
|
||||
#setdims#
|
||||
#ifdef PYPY_VERSION
|
||||
#define CAPI_ARGLIST_SETITEM(idx, value) PyList_SetItem((PyObject *)capi_arglist_list, idx, value)
|
||||
capi_arglist_list = PySequence_List((PyObject *)capi_arglist);
|
||||
if (capi_arglist_list == NULL) goto capi_fail;
|
||||
#else
|
||||
#define CAPI_ARGLIST_SETITEM(idx, value) PyTuple_SetItem((PyObject *)capi_arglist, idx, value)
|
||||
#endif
|
||||
#pyobjfrom#
|
||||
#undef CAPI_ARGLIST_SETITEM
|
||||
#ifdef PYPY_VERSION
|
||||
CFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist_list);
|
||||
#else
|
||||
CFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist);
|
||||
#endif
|
||||
CFUNCSMESS(\"cb:Call-back calling Python function #argname#.\\n\");
|
||||
#ifdef F2PY_REPORT_ATEXIT
|
||||
f2py_cb_start_call_clock();
|
||||
#endif
|
||||
#ifdef PYPY_VERSION
|
||||
capi_return = PyObject_CallObject(cb->capi,(PyObject *)capi_arglist_list);
|
||||
Py_DECREF(capi_arglist_list);
|
||||
capi_arglist_list = NULL;
|
||||
#else
|
||||
capi_return = PyObject_CallObject(cb->capi,(PyObject *)capi_arglist);
|
||||
#endif
|
||||
#ifdef F2PY_REPORT_ATEXIT
|
||||
f2py_cb_stop_call_clock();
|
||||
#endif
|
||||
CFUNCSMESSPY(\"cb:capi_return=\",capi_return);
|
||||
if (capi_return == NULL) {
|
||||
fprintf(stderr,\"capi_return is NULL\\n\");
|
||||
goto capi_fail;
|
||||
}
|
||||
if (capi_return == Py_None) {
|
||||
Py_DECREF(capi_return);
|
||||
capi_return = Py_BuildValue(\"()\");
|
||||
}
|
||||
else if (!PyTuple_Check(capi_return)) {
|
||||
capi_return = Py_BuildValue(\"(N)\",capi_return);
|
||||
}
|
||||
capi_j = PyTuple_Size(capi_return);
|
||||
capi_i = 0;
|
||||
#frompyobj#
|
||||
CFUNCSMESS(\"cb:#name#:successful\\n\");
|
||||
Py_DECREF(capi_return);
|
||||
#ifdef F2PY_REPORT_ATEXIT
|
||||
f2py_cb_stop_clock();
|
||||
#endif
|
||||
goto capi_return_pt;
|
||||
capi_fail:
|
||||
fprintf(stderr,\"Call-back #name# failed.\\n\");
|
||||
Py_XDECREF(capi_return);
|
||||
Py_XDECREF(capi_arglist_list);
|
||||
if (capi_longjmp_ok) {
|
||||
longjmp(cb->jmpbuf,-1);
|
||||
}
|
||||
capi_return_pt:
|
||||
;
|
||||
#return#
|
||||
}
|
||||
#endtitle#
|
||||
""",
|
||||
'need': ['setjmp.h', 'CFUNCSMESS', 'F2PY_THREAD_LOCAL_DECL'],
|
||||
'maxnofargs': '#maxnofargs#',
|
||||
'nofoptargs': '#nofoptargs#',
|
||||
'docstr': """\
|
||||
def #argname#(#docsignature#): return #docreturn#\\n\\
|
||||
#docstrsigns#""",
|
||||
'latexdocstr': """
|
||||
{{}\\verb@def #argname#(#latexdocsignature#): return #docreturn#@{}}
|
||||
#routnote#
|
||||
|
||||
#latexdocstrsigns#""",
|
||||
'docstrshort': 'def #argname#(#docsignature#): return #docreturn#'
|
||||
}
|
||||
cb_rout_rules = [
|
||||
{ # Init
|
||||
'separatorsfor': {'decl': '\n',
|
||||
'args': ',', 'optargs': '', 'pyobjfrom': '\n', 'freemem': '\n',
|
||||
'args_td': ',', 'optargs_td': '',
|
||||
'args_nm': ',', 'optargs_nm': '',
|
||||
'frompyobj': '\n', 'setdims': '\n',
|
||||
'docstrsigns': '\\n"\n"',
|
||||
'latexdocstrsigns': '\n',
|
||||
'latexdocstrreq': '\n', 'latexdocstropt': '\n',
|
||||
'latexdocstrout': '\n', 'latexdocstrcbs': '\n',
|
||||
},
|
||||
'decl': '/*decl*/', 'pyobjfrom': '/*pyobjfrom*/', 'frompyobj': '/*frompyobj*/',
|
||||
'args': [], 'optargs': '', 'return': '', 'strarglens': '', 'freemem': '/*freemem*/',
|
||||
'args_td': [], 'optargs_td': '', 'strarglens_td': '',
|
||||
'args_nm': [], 'optargs_nm': '', 'strarglens_nm': '',
|
||||
'noargs': '',
|
||||
'setdims': '/*setdims*/',
|
||||
'docstrsigns': '', 'latexdocstrsigns': '',
|
||||
'docstrreq': ' Required arguments:',
|
||||
'docstropt': ' Optional arguments:',
|
||||
'docstrout': ' Return objects:',
|
||||
'docstrcbs': ' Call-back functions:',
|
||||
'docreturn': '', 'docsign': '', 'docsignopt': '',
|
||||
'latexdocstrreq': '\\noindent Required arguments:',
|
||||
'latexdocstropt': '\\noindent Optional arguments:',
|
||||
'latexdocstrout': '\\noindent Return objects:',
|
||||
'latexdocstrcbs': '\\noindent Call-back functions:',
|
||||
'routnote': {hasnote: '--- #note#', l_not(hasnote): ''},
|
||||
}, { # Function
|
||||
'decl': ' #ctype# return_value = 0;',
|
||||
'frompyobj': [
|
||||
{debugcapi: ' CFUNCSMESS("cb:Getting return_value->");'},
|
||||
'''\
|
||||
if (capi_j>capi_i) {
|
||||
GETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,
|
||||
"#ctype#_from_pyobj failed in converting return_value of"
|
||||
" call-back function #name# to C #ctype#\\n");
|
||||
} else {
|
||||
fprintf(stderr,"Warning: call-back function #name# did not provide"
|
||||
" return value (index=%d, type=#ctype#)\\n",capi_i);
|
||||
}''',
|
||||
{debugcapi:
|
||||
' fprintf(stderr,"#showvalueformat#.\\n",return_value);'}
|
||||
],
|
||||
'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'}, 'GETSCALARFROMPYTUPLE'],
|
||||
'return': ' return return_value;',
|
||||
'_check': l_and(isfunction, l_not(isstringfunction), l_not(iscomplexfunction))
|
||||
},
|
||||
{ # String function
|
||||
'pyobjfrom': {debugcapi: ' fprintf(stderr,"debug-capi:cb:#name#:%d:\\n",return_value_len);'},
|
||||
'args': '#ctype# return_value,int return_value_len',
|
||||
'args_nm': 'return_value,&return_value_len',
|
||||
'args_td': '#ctype# ,int',
|
||||
'frompyobj': [
|
||||
{debugcapi: ' CFUNCSMESS("cb:Getting return_value->\\"");'},
|
||||
"""\
|
||||
if (capi_j>capi_i) {
|
||||
GETSTRFROMPYTUPLE(capi_return,capi_i++,return_value,return_value_len);
|
||||
} else {
|
||||
fprintf(stderr,"Warning: call-back function #name# did not provide"
|
||||
" return value (index=%d, type=#ctype#)\\n",capi_i);
|
||||
}""",
|
||||
{debugcapi:
|
||||
' fprintf(stderr,"#showvalueformat#\\".\\n",return_value);'}
|
||||
],
|
||||
'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'},
|
||||
'string.h', 'GETSTRFROMPYTUPLE'],
|
||||
'return': 'return;',
|
||||
'_check': isstringfunction
|
||||
},
|
||||
{ # Complex function
|
||||
'optargs': """
|
||||
#ifndef F2PY_CB_RETURNCOMPLEX
|
||||
#ctype# *return_value
|
||||
#endif
|
||||
""",
|
||||
'optargs_nm': """
|
||||
#ifndef F2PY_CB_RETURNCOMPLEX
|
||||
return_value
|
||||
#endif
|
||||
""",
|
||||
'optargs_td': """
|
||||
#ifndef F2PY_CB_RETURNCOMPLEX
|
||||
#ctype# *
|
||||
#endif
|
||||
""",
|
||||
'decl': """
|
||||
#ifdef F2PY_CB_RETURNCOMPLEX
|
||||
#ctype# return_value = {0, 0};
|
||||
#endif
|
||||
""",
|
||||
'frompyobj': [
|
||||
{debugcapi: ' CFUNCSMESS("cb:Getting return_value->");'},
|
||||
"""\
|
||||
if (capi_j>capi_i) {
|
||||
#ifdef F2PY_CB_RETURNCOMPLEX
|
||||
GETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,
|
||||
\"#ctype#_from_pyobj failed in converting return_value of call-back\"
|
||||
\" function #name# to C #ctype#\\n\");
|
||||
#else
|
||||
GETSCALARFROMPYTUPLE(capi_return,capi_i++,return_value,#ctype#,
|
||||
\"#ctype#_from_pyobj failed in converting return_value of call-back\"
|
||||
\" function #name# to C #ctype#\\n\");
|
||||
#endif
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
\"Warning: call-back function #name# did not provide\"
|
||||
\" return value (index=%d, type=#ctype#)\\n\",capi_i);
|
||||
}""",
|
||||
{debugcapi: """\
|
||||
#ifdef F2PY_CB_RETURNCOMPLEX
|
||||
fprintf(stderr,\"#showvalueformat#.\\n\",(return_value).r,(return_value).i);
|
||||
#else
|
||||
fprintf(stderr,\"#showvalueformat#.\\n\",(*return_value).r,(*return_value).i);
|
||||
#endif
|
||||
"""}
|
||||
],
|
||||
'return': """
|
||||
#ifdef F2PY_CB_RETURNCOMPLEX
|
||||
return return_value;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
""",
|
||||
'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'},
|
||||
'string.h', 'GETSCALARFROMPYTUPLE', '#ctype#'],
|
||||
'_check': iscomplexfunction
|
||||
},
|
||||
{'docstrout': ' #pydocsignout#',
|
||||
'latexdocstrout': ['\\item[]{{}\\verb@#pydocsignout#@{}}',
|
||||
{hasnote: '--- #note#'}],
|
||||
'docreturn': '#rname#,',
|
||||
'_check': isfunction},
|
||||
{'_check': issubroutine, 'return': 'return;'}
|
||||
]
|
||||
|
||||
cb_arg_rules = [
|
||||
{ # Doc
|
||||
'docstropt': {l_and(isoptional, isintent_nothide): ' #pydocsign#'},
|
||||
'docstrreq': {l_and(isrequired, isintent_nothide): ' #pydocsign#'},
|
||||
'docstrout': {isintent_out: ' #pydocsignout#'},
|
||||
'latexdocstropt': {l_and(isoptional, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
|
||||
{hasnote: '--- #note#'}]},
|
||||
'latexdocstrreq': {l_and(isrequired, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
|
||||
{hasnote: '--- #note#'}]},
|
||||
'latexdocstrout': {isintent_out: ['\\item[]{{}\\verb@#pydocsignout#@{}}',
|
||||
{l_and(hasnote, isintent_hide): '--- #note#',
|
||||
l_and(hasnote, isintent_nothide): '--- See above.'}]},
|
||||
'docsign': {l_and(isrequired, isintent_nothide): '#varname#,'},
|
||||
'docsignopt': {l_and(isoptional, isintent_nothide): '#varname#,'},
|
||||
'depend': ''
|
||||
},
|
||||
{
|
||||
'args': {
|
||||
l_and(isscalar, isintent_c): '#ctype# #varname_i#',
|
||||
l_and(isscalar, l_not(isintent_c)): '#ctype# *#varname_i#_cb_capi',
|
||||
isarray: '#ctype# *#varname_i#',
|
||||
isstring: '#ctype# #varname_i#'
|
||||
},
|
||||
'args_nm': {
|
||||
l_and(isscalar, isintent_c): '#varname_i#',
|
||||
l_and(isscalar, l_not(isintent_c)): '#varname_i#_cb_capi',
|
||||
isarray: '#varname_i#',
|
||||
isstring: '#varname_i#'
|
||||
},
|
||||
'args_td': {
|
||||
l_and(isscalar, isintent_c): '#ctype#',
|
||||
l_and(isscalar, l_not(isintent_c)): '#ctype# *',
|
||||
isarray: '#ctype# *',
|
||||
isstring: '#ctype#'
|
||||
},
|
||||
'need': {l_or(isscalar, isarray, isstring): '#ctype#'},
|
||||
# untested with multiple args
|
||||
'strarglens': {isstring: ',int #varname_i#_cb_len'},
|
||||
'strarglens_td': {isstring: ',int'}, # untested with multiple args
|
||||
# untested with multiple args
|
||||
'strarglens_nm': {isstring: ',#varname_i#_cb_len'},
|
||||
},
|
||||
{ # Scalars
|
||||
'decl': {l_not(isintent_c): ' #ctype# #varname_i#=(*#varname_i#_cb_capi);'},
|
||||
'error': {l_and(isintent_c, isintent_out,
|
||||
throw_error('intent(c,out) is forbidden for callback scalar arguments')):
|
||||
''},
|
||||
'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->");'},
|
||||
{isintent_out:
|
||||
' if (capi_j>capi_i)\n GETSCALARFROMPYTUPLE(capi_return,capi_i++,#varname_i#_cb_capi,#ctype#,"#ctype#_from_pyobj failed in converting argument #varname# of call-back function #name# to C #ctype#\\n");'},
|
||||
{l_and(debugcapi, l_and(l_not(iscomplex), isintent_c)):
|
||||
' fprintf(stderr,"#showvalueformat#.\\n",#varname_i#);'},
|
||||
{l_and(debugcapi, l_and(l_not(iscomplex), l_not( isintent_c))):
|
||||
' fprintf(stderr,"#showvalueformat#.\\n",*#varname_i#_cb_capi);'},
|
||||
{l_and(debugcapi, l_and(iscomplex, isintent_c)):
|
||||
' fprintf(stderr,"#showvalueformat#.\\n",(#varname_i#).r,(#varname_i#).i);'},
|
||||
{l_and(debugcapi, l_and(iscomplex, l_not( isintent_c))):
|
||||
' fprintf(stderr,"#showvalueformat#.\\n",(*#varname_i#_cb_capi).r,(*#varname_i#_cb_capi).i);'},
|
||||
],
|
||||
'need': [{isintent_out: ['#ctype#_from_pyobj', 'GETSCALARFROMPYTUPLE']},
|
||||
{debugcapi: 'CFUNCSMESS'}],
|
||||
'_check': isscalar
|
||||
}, {
|
||||
'pyobjfrom': [{isintent_in: """\
|
||||
if (cb->nofargs>capi_i)
|
||||
if (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1(#varname_i#)))
|
||||
goto capi_fail;"""},
|
||||
{isintent_inout: """\
|
||||
if (cb->nofargs>capi_i)
|
||||
if (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#_cb_capi)))
|
||||
goto capi_fail;"""}],
|
||||
'need': [{isintent_in: 'pyobj_from_#ctype#1'},
|
||||
{isintent_inout: 'pyarr_from_p_#ctype#1'},
|
||||
{iscomplex: '#ctype#'}],
|
||||
'_check': l_and(isscalar, isintent_nothide),
|
||||
'_optional': ''
|
||||
}, { # String
|
||||
'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->\\"");'},
|
||||
""" if (capi_j>capi_i)
|
||||
GETSTRFROMPYTUPLE(capi_return,capi_i++,#varname_i#,#varname_i#_cb_len);""",
|
||||
{debugcapi:
|
||||
' fprintf(stderr,"#showvalueformat#\\":%d:.\\n",#varname_i#,#varname_i#_cb_len);'},
|
||||
],
|
||||
'need': ['#ctype#', 'GETSTRFROMPYTUPLE',
|
||||
{debugcapi: 'CFUNCSMESS'}, 'string.h'],
|
||||
'_check': l_and(isstring, isintent_out)
|
||||
}, {
|
||||
'pyobjfrom': [
|
||||
{debugcapi:
|
||||
(' fprintf(stderr,"debug-capi:cb:#varname#=#showvalueformat#:'
|
||||
'%d:\\n",#varname_i#,#varname_i#_cb_len);')},
|
||||
{isintent_in: """\
|
||||
if (cb->nofargs>capi_i)
|
||||
if (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1size(#varname_i#,#varname_i#_cb_len)))
|
||||
goto capi_fail;"""},
|
||||
{isintent_inout: """\
|
||||
if (cb->nofargs>capi_i) {
|
||||
int #varname_i#_cb_dims[] = {#varname_i#_cb_len};
|
||||
if (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#,#varname_i#_cb_dims)))
|
||||
goto capi_fail;
|
||||
}"""}],
|
||||
'need': [{isintent_in: 'pyobj_from_#ctype#1size'},
|
||||
{isintent_inout: 'pyarr_from_p_#ctype#1'}],
|
||||
'_check': l_and(isstring, isintent_nothide),
|
||||
'_optional': ''
|
||||
},
|
||||
# Array ...
|
||||
{
|
||||
'decl': ' npy_intp #varname_i#_Dims[#rank#] = {#rank*[-1]#};',
|
||||
'setdims': ' #cbsetdims#;',
|
||||
'_check': isarray,
|
||||
'_depend': ''
|
||||
},
|
||||
{
|
||||
'pyobjfrom': [{debugcapi: ' fprintf(stderr,"debug-capi:cb:#varname#\\n");'},
|
||||
{isintent_c: """\
|
||||
if (cb->nofargs>capi_i) {
|
||||
/* tmp_arr will be inserted to capi_arglist_list that will be
|
||||
destroyed when leaving callback function wrapper together
|
||||
with tmp_arr. */
|
||||
PyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,
|
||||
#rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,#elsize#,
|
||||
NPY_ARRAY_CARRAY,NULL);
|
||||
""",
|
||||
l_not(isintent_c): """\
|
||||
if (cb->nofargs>capi_i) {
|
||||
/* tmp_arr will be inserted to capi_arglist_list that will be
|
||||
destroyed when leaving callback function wrapper together
|
||||
with tmp_arr. */
|
||||
PyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,
|
||||
#rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,#elsize#,
|
||||
NPY_ARRAY_FARRAY,NULL);
|
||||
""",
|
||||
},
|
||||
"""
|
||||
if (tmp_arr==NULL)
|
||||
goto capi_fail;
|
||||
if (CAPI_ARGLIST_SETITEM(capi_i++,(PyObject *)tmp_arr))
|
||||
goto capi_fail;
|
||||
}"""],
|
||||
'_check': l_and(isarray, isintent_nothide, l_or(isintent_in, isintent_inout)),
|
||||
'_optional': '',
|
||||
}, {
|
||||
'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->");'},
|
||||
""" if (capi_j>capi_i) {
|
||||
PyArrayObject *rv_cb_arr = NULL;
|
||||
if ((capi_tmp = PyTuple_GetItem(capi_return,capi_i++))==NULL) goto capi_fail;
|
||||
rv_cb_arr = array_from_pyobj(#atype#,#varname_i#_Dims,#rank#,F2PY_INTENT_IN""",
|
||||
{isintent_c: '|F2PY_INTENT_C'},
|
||||
""",capi_tmp);
|
||||
if (rv_cb_arr == NULL) {
|
||||
fprintf(stderr,\"rv_cb_arr is NULL\\n\");
|
||||
goto capi_fail;
|
||||
}
|
||||
MEMCOPY(#varname_i#,PyArray_DATA(rv_cb_arr),PyArray_NBYTES(rv_cb_arr));
|
||||
if (capi_tmp != (PyObject *)rv_cb_arr) {
|
||||
Py_DECREF(rv_cb_arr);
|
||||
}
|
||||
}""",
|
||||
{debugcapi: ' fprintf(stderr,"<-.\\n");'},
|
||||
],
|
||||
'need': ['MEMCOPY', {iscomplexarray: '#ctype#'}],
|
||||
'_check': l_and(isarray, isintent_out)
|
||||
}, {
|
||||
'docreturn': '#varname#,',
|
||||
'_check': isintent_out
|
||||
}
|
||||
]
|
||||
|
||||
################## Build call-back module #############
|
||||
cb_map = {}
|
||||
|
||||
|
||||
def buildcallbacks(m):
|
||||
cb_map[m['name']] = []
|
||||
for bi in m['body']:
|
||||
if bi['block'] == 'interface':
|
||||
for b in bi['body']:
|
||||
if b:
|
||||
buildcallback(b, m['name'])
|
||||
else:
|
||||
errmess('warning: empty body for %s\n' % (m['name']))
|
||||
|
||||
|
||||
def buildcallback(rout, um):
|
||||
from . import capi_maps
|
||||
|
||||
outmess(' Constructing call-back function "cb_%s_in_%s"\n' %
|
||||
(rout['name'], um))
|
||||
args, depargs = getargs(rout)
|
||||
capi_maps.depargs = depargs
|
||||
var = rout['vars']
|
||||
vrd = capi_maps.cb_routsign2map(rout, um)
|
||||
rd = dictappend({}, vrd)
|
||||
cb_map[um].append([rout['name'], rd['name']])
|
||||
for r in cb_rout_rules:
|
||||
if ('_check' in r and r['_check'](rout)) or ('_check' not in r):
|
||||
ar = applyrules(r, vrd, rout)
|
||||
rd = dictappend(rd, ar)
|
||||
savevrd = {}
|
||||
for i, a in enumerate(args):
|
||||
vrd = capi_maps.cb_sign2map(a, var[a], index=i)
|
||||
savevrd[a] = vrd
|
||||
for r in cb_arg_rules:
|
||||
if '_depend' in r:
|
||||
continue
|
||||
if '_optional' in r and isoptional(var[a]):
|
||||
continue
|
||||
if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
|
||||
ar = applyrules(r, vrd, var[a])
|
||||
rd = dictappend(rd, ar)
|
||||
if '_break' in r:
|
||||
break
|
||||
for a in args:
|
||||
vrd = savevrd[a]
|
||||
for r in cb_arg_rules:
|
||||
if '_depend' in r:
|
||||
continue
|
||||
if ('_optional' not in r) or ('_optional' in r and isrequired(var[a])):
|
||||
continue
|
||||
if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
|
||||
ar = applyrules(r, vrd, var[a])
|
||||
rd = dictappend(rd, ar)
|
||||
if '_break' in r:
|
||||
break
|
||||
for a in depargs:
|
||||
vrd = savevrd[a]
|
||||
for r in cb_arg_rules:
|
||||
if '_depend' not in r:
|
||||
continue
|
||||
if '_optional' in r:
|
||||
continue
|
||||
if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
|
||||
ar = applyrules(r, vrd, var[a])
|
||||
rd = dictappend(rd, ar)
|
||||
if '_break' in r:
|
||||
break
|
||||
if 'args' in rd and 'optargs' in rd:
|
||||
if isinstance(rd['optargs'], list):
|
||||
rd['optargs'] = rd['optargs'] + ["""
|
||||
#ifndef F2PY_CB_RETURNCOMPLEX
|
||||
,
|
||||
#endif
|
||||
"""]
|
||||
rd['optargs_nm'] = rd['optargs_nm'] + ["""
|
||||
#ifndef F2PY_CB_RETURNCOMPLEX
|
||||
,
|
||||
#endif
|
||||
"""]
|
||||
rd['optargs_td'] = rd['optargs_td'] + ["""
|
||||
#ifndef F2PY_CB_RETURNCOMPLEX
|
||||
,
|
||||
#endif
|
||||
"""]
|
||||
if isinstance(rd['docreturn'], list):
|
||||
rd['docreturn'] = stripcomma(
|
||||
replace('#docreturn#', {'docreturn': rd['docreturn']}))
|
||||
optargs = stripcomma(replace('#docsignopt#',
|
||||
{'docsignopt': rd['docsignopt']}
|
||||
))
|
||||
if optargs == '':
|
||||
rd['docsignature'] = stripcomma(
|
||||
replace('#docsign#', {'docsign': rd['docsign']}))
|
||||
else:
|
||||
rd['docsignature'] = replace('#docsign#[#docsignopt#]',
|
||||
{'docsign': rd['docsign'],
|
||||
'docsignopt': optargs,
|
||||
})
|
||||
rd['latexdocsignature'] = rd['docsignature'].replace('_', '\\_')
|
||||
rd['latexdocsignature'] = rd['latexdocsignature'].replace(',', ', ')
|
||||
rd['docstrsigns'] = []
|
||||
rd['latexdocstrsigns'] = []
|
||||
for k in ['docstrreq', 'docstropt', 'docstrout', 'docstrcbs']:
|
||||
if k in rd and isinstance(rd[k], list):
|
||||
rd['docstrsigns'] = rd['docstrsigns'] + rd[k]
|
||||
k = 'latex' + k
|
||||
if k in rd and isinstance(rd[k], list):
|
||||
rd['latexdocstrsigns'] = rd['latexdocstrsigns'] + rd[k][0:1] +\
|
||||
['\\begin{description}'] + rd[k][1:] +\
|
||||
['\\end{description}']
|
||||
if 'args' not in rd:
|
||||
rd['args'] = ''
|
||||
rd['args_td'] = ''
|
||||
rd['args_nm'] = ''
|
||||
if not (rd.get('args') or rd.get('optargs') or rd.get('strarglens')):
|
||||
rd['noargs'] = 'void'
|
||||
|
||||
ar = applyrules(cb_routine_rules, rd)
|
||||
cfuncs.callbacks[rd['name']] = ar['body']
|
||||
if isinstance(ar['need'], str):
|
||||
ar['need'] = [ar['need']]
|
||||
|
||||
if 'need' in rd:
|
||||
for t in cfuncs.typedefs.keys():
|
||||
if t in rd['need']:
|
||||
ar['need'].append(t)
|
||||
|
||||
cfuncs.typedefs_generated[rd['name'] + '_typedef'] = ar['cbtypedefs']
|
||||
ar['need'].append(rd['name'] + '_typedef')
|
||||
cfuncs.needs[rd['name']] = ar['need']
|
||||
|
||||
capi_maps.lcb2_map[rd['name']] = {'maxnofargs': ar['maxnofargs'],
|
||||
'nofoptargs': ar['nofoptargs'],
|
||||
'docstr': ar['docstr'],
|
||||
'latexdocstr': ar['latexdocstr'],
|
||||
'argname': rd['argname']
|
||||
}
|
||||
outmess(' %s\n' % (ar['docstrshort']))
|
||||
return
|
||||
################## Build call-back function #############
|
1545
lib/python3.13/site-packages/numpy/f2py/cfuncs.py
Normal file
1545
lib/python3.13/site-packages/numpy/f2py/cfuncs.py
Normal file
File diff suppressed because it is too large
Load Diff
146
lib/python3.13/site-packages/numpy/f2py/common_rules.py
Normal file
146
lib/python3.13/site-packages/numpy/f2py/common_rules.py
Normal file
@ -0,0 +1,146 @@
|
||||
"""
|
||||
Build common block mechanism for f2py2e.
|
||||
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
Permission to use, modify, and distribute this software is given under the
|
||||
terms of the NumPy License
|
||||
|
||||
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
"""
|
||||
from . import __version__
|
||||
f2py_version = __version__.version
|
||||
|
||||
from .auxfuncs import (
|
||||
hasbody, hascommon, hasnote, isintent_hide, outmess, getuseblocks
|
||||
)
|
||||
from . import capi_maps
|
||||
from . import func2subr
|
||||
from .crackfortran import rmbadname
|
||||
|
||||
|
||||
def findcommonblocks(block, top=1):
|
||||
ret = []
|
||||
if hascommon(block):
|
||||
for key, value in block['common'].items():
|
||||
vars_ = {v: block['vars'][v] for v in value}
|
||||
ret.append((key, value, vars_))
|
||||
elif hasbody(block):
|
||||
for b in block['body']:
|
||||
ret = ret + findcommonblocks(b, 0)
|
||||
if top:
|
||||
tret = []
|
||||
names = []
|
||||
for t in ret:
|
||||
if t[0] not in names:
|
||||
names.append(t[0])
|
||||
tret.append(t)
|
||||
return tret
|
||||
return ret
|
||||
|
||||
|
||||
def buildhooks(m):
|
||||
ret = {'commonhooks': [], 'initcommonhooks': [],
|
||||
'docs': ['"COMMON blocks:\\n"']}
|
||||
fwrap = ['']
|
||||
|
||||
def fadd(line, s=fwrap):
|
||||
s[0] = '%s\n %s' % (s[0], line)
|
||||
chooks = ['']
|
||||
|
||||
def cadd(line, s=chooks):
|
||||
s[0] = '%s\n%s' % (s[0], line)
|
||||
ihooks = ['']
|
||||
|
||||
def iadd(line, s=ihooks):
|
||||
s[0] = '%s\n%s' % (s[0], line)
|
||||
doc = ['']
|
||||
|
||||
def dadd(line, s=doc):
|
||||
s[0] = '%s\n%s' % (s[0], line)
|
||||
for (name, vnames, vars) in findcommonblocks(m):
|
||||
lower_name = name.lower()
|
||||
hnames, inames = [], []
|
||||
for n in vnames:
|
||||
if isintent_hide(vars[n]):
|
||||
hnames.append(n)
|
||||
else:
|
||||
inames.append(n)
|
||||
if hnames:
|
||||
outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n\t\t Hidden: %s\n' % (
|
||||
name, ','.join(inames), ','.join(hnames)))
|
||||
else:
|
||||
outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n' % (
|
||||
name, ','.join(inames)))
|
||||
fadd('subroutine f2pyinit%s(setupfunc)' % name)
|
||||
for usename in getuseblocks(m):
|
||||
fadd(f'use {usename}')
|
||||
fadd('external setupfunc')
|
||||
for n in vnames:
|
||||
fadd(func2subr.var2fixfortran(vars, n))
|
||||
if name == '_BLNK_':
|
||||
fadd('common %s' % (','.join(vnames)))
|
||||
else:
|
||||
fadd('common /%s/ %s' % (name, ','.join(vnames)))
|
||||
fadd('call setupfunc(%s)' % (','.join(inames)))
|
||||
fadd('end\n')
|
||||
cadd('static FortranDataDef f2py_%s_def[] = {' % (name))
|
||||
idims = []
|
||||
for n in inames:
|
||||
ct = capi_maps.getctype(vars[n])
|
||||
elsize = capi_maps.get_elsize(vars[n])
|
||||
at = capi_maps.c2capi_map[ct]
|
||||
dm = capi_maps.getarrdims(n, vars[n])
|
||||
if dm['dims']:
|
||||
idims.append('(%s)' % (dm['dims']))
|
||||
else:
|
||||
idims.append('')
|
||||
dms = dm['dims'].strip()
|
||||
if not dms:
|
||||
dms = '-1'
|
||||
cadd('\t{\"%s\",%s,{{%s}},%s, %s},'
|
||||
% (n, dm['rank'], dms, at, elsize))
|
||||
cadd('\t{NULL}\n};')
|
||||
inames1 = rmbadname(inames)
|
||||
inames1_tps = ','.join(['char *' + s for s in inames1])
|
||||
cadd('static void f2py_setup_%s(%s) {' % (name, inames1_tps))
|
||||
cadd('\tint i_f2py=0;')
|
||||
for n in inames1:
|
||||
cadd('\tf2py_%s_def[i_f2py++].data = %s;' % (name, n))
|
||||
cadd('}')
|
||||
if '_' in lower_name:
|
||||
F_FUNC = 'F_FUNC_US'
|
||||
else:
|
||||
F_FUNC = 'F_FUNC'
|
||||
cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
|
||||
% (F_FUNC, lower_name, name.upper(),
|
||||
','.join(['char*'] * len(inames1))))
|
||||
cadd('static void f2py_init_%s(void) {' % name)
|
||||
cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
|
||||
% (F_FUNC, lower_name, name.upper(), name))
|
||||
cadd('}\n')
|
||||
iadd('\ttmp = PyFortranObject_New(f2py_%s_def,f2py_init_%s);' % (name, name))
|
||||
iadd('\tif (tmp == NULL) return NULL;')
|
||||
iadd('\tif (F2PyDict_SetItemString(d, \"%s\", tmp) == -1) return NULL;'
|
||||
% name)
|
||||
iadd('\tPy_DECREF(tmp);')
|
||||
tname = name.replace('_', '\\_')
|
||||
dadd('\\subsection{Common block \\texttt{%s}}\n' % (tname))
|
||||
dadd('\\begin{description}')
|
||||
for n in inames:
|
||||
dadd('\\item[]{{}\\verb@%s@{}}' %
|
||||
(capi_maps.getarrdocsign(n, vars[n])))
|
||||
if hasnote(vars[n]):
|
||||
note = vars[n]['note']
|
||||
if isinstance(note, list):
|
||||
note = '\n'.join(note)
|
||||
dadd('--- %s' % (note))
|
||||
dadd('\\end{description}')
|
||||
ret['docs'].append(
|
||||
'"\t/%s/ %s\\n"' % (name, ','.join(map(lambda v, d: v + d, inames, idims))))
|
||||
ret['commonhooks'] = chooks
|
||||
ret['initcommonhooks'] = ihooks
|
||||
ret['latexdoc'] = doc[0]
|
||||
if len(ret['docs']) <= 1:
|
||||
ret['docs'] = ''
|
||||
return ret, fwrap[0]
|
3755
lib/python3.13/site-packages/numpy/f2py/crackfortran.py
Executable file
3755
lib/python3.13/site-packages/numpy/f2py/crackfortran.py
Executable file
File diff suppressed because it is too large
Load Diff
154
lib/python3.13/site-packages/numpy/f2py/diagnose.py
Normal file
154
lib/python3.13/site-packages/numpy/f2py/diagnose.py
Normal file
@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
|
||||
def run_command(cmd):
|
||||
print('Running %r:' % (cmd))
|
||||
os.system(cmd)
|
||||
print('------')
|
||||
|
||||
|
||||
def run():
|
||||
_path = os.getcwd()
|
||||
os.chdir(tempfile.gettempdir())
|
||||
print('------')
|
||||
print('os.name=%r' % (os.name))
|
||||
print('------')
|
||||
print('sys.platform=%r' % (sys.platform))
|
||||
print('------')
|
||||
print('sys.version:')
|
||||
print(sys.version)
|
||||
print('------')
|
||||
print('sys.prefix:')
|
||||
print(sys.prefix)
|
||||
print('------')
|
||||
print('sys.path=%r' % (':'.join(sys.path)))
|
||||
print('------')
|
||||
|
||||
try:
|
||||
import numpy
|
||||
has_newnumpy = 1
|
||||
except ImportError as e:
|
||||
print('Failed to import new numpy:', e)
|
||||
has_newnumpy = 0
|
||||
|
||||
try:
|
||||
from numpy.f2py import f2py2e
|
||||
has_f2py2e = 1
|
||||
except ImportError as e:
|
||||
print('Failed to import f2py2e:', e)
|
||||
has_f2py2e = 0
|
||||
|
||||
try:
|
||||
import numpy.distutils
|
||||
has_numpy_distutils = 2
|
||||
except ImportError:
|
||||
try:
|
||||
import numpy_distutils
|
||||
has_numpy_distutils = 1
|
||||
except ImportError as e:
|
||||
print('Failed to import numpy_distutils:', e)
|
||||
has_numpy_distutils = 0
|
||||
|
||||
if has_newnumpy:
|
||||
try:
|
||||
print('Found new numpy version %r in %s' %
|
||||
(numpy.__version__, numpy.__file__))
|
||||
except Exception as msg:
|
||||
print('error:', msg)
|
||||
print('------')
|
||||
|
||||
if has_f2py2e:
|
||||
try:
|
||||
print('Found f2py2e version %r in %s' %
|
||||
(f2py2e.__version__.version, f2py2e.__file__))
|
||||
except Exception as msg:
|
||||
print('error:', msg)
|
||||
print('------')
|
||||
|
||||
if has_numpy_distutils:
|
||||
try:
|
||||
if has_numpy_distutils == 2:
|
||||
print('Found numpy.distutils version %r in %r' % (
|
||||
numpy.distutils.__version__,
|
||||
numpy.distutils.__file__))
|
||||
else:
|
||||
print('Found numpy_distutils version %r in %r' % (
|
||||
numpy_distutils.numpy_distutils_version.numpy_distutils_version,
|
||||
numpy_distutils.__file__))
|
||||
print('------')
|
||||
except Exception as msg:
|
||||
print('error:', msg)
|
||||
print('------')
|
||||
try:
|
||||
if has_numpy_distutils == 1:
|
||||
print(
|
||||
'Importing numpy_distutils.command.build_flib ...', end=' ')
|
||||
import numpy_distutils.command.build_flib as build_flib
|
||||
print('ok')
|
||||
print('------')
|
||||
try:
|
||||
print(
|
||||
'Checking availability of supported Fortran compilers:')
|
||||
for compiler_class in build_flib.all_compilers:
|
||||
compiler_class(verbose=1).is_available()
|
||||
print('------')
|
||||
except Exception as msg:
|
||||
print('error:', msg)
|
||||
print('------')
|
||||
except Exception as msg:
|
||||
print(
|
||||
'error:', msg, '(ignore it, build_flib is obsolute for numpy.distutils 0.2.2 and up)')
|
||||
print('------')
|
||||
try:
|
||||
if has_numpy_distutils == 2:
|
||||
print('Importing numpy.distutils.fcompiler ...', end=' ')
|
||||
import numpy.distutils.fcompiler as fcompiler
|
||||
else:
|
||||
print('Importing numpy_distutils.fcompiler ...', end=' ')
|
||||
import numpy_distutils.fcompiler as fcompiler
|
||||
print('ok')
|
||||
print('------')
|
||||
try:
|
||||
print('Checking availability of supported Fortran compilers:')
|
||||
fcompiler.show_fcompilers()
|
||||
print('------')
|
||||
except Exception as msg:
|
||||
print('error:', msg)
|
||||
print('------')
|
||||
except Exception as msg:
|
||||
print('error:', msg)
|
||||
print('------')
|
||||
try:
|
||||
if has_numpy_distutils == 2:
|
||||
print('Importing numpy.distutils.cpuinfo ...', end=' ')
|
||||
from numpy.distutils.cpuinfo import cpuinfo
|
||||
print('ok')
|
||||
print('------')
|
||||
else:
|
||||
try:
|
||||
print(
|
||||
'Importing numpy_distutils.command.cpuinfo ...', end=' ')
|
||||
from numpy_distutils.command.cpuinfo import cpuinfo
|
||||
print('ok')
|
||||
print('------')
|
||||
except Exception as msg:
|
||||
print('error:', msg, '(ignore it)')
|
||||
print('Importing numpy_distutils.cpuinfo ...', end=' ')
|
||||
from numpy_distutils.cpuinfo import cpuinfo
|
||||
print('ok')
|
||||
print('------')
|
||||
cpu = cpuinfo()
|
||||
print('CPU information:', end=' ')
|
||||
for name in dir(cpuinfo):
|
||||
if name[0] == '_' and name[1] != '_' and getattr(cpu, name[1:])():
|
||||
print(name[1:], end=' ')
|
||||
print('------')
|
||||
except Exception as msg:
|
||||
print('error:', msg)
|
||||
print('------')
|
||||
os.chdir(_path)
|
||||
if __name__ == "__main__":
|
||||
run()
|
787
lib/python3.13/site-packages/numpy/f2py/f2py2e.py
Executable file
787
lib/python3.13/site-packages/numpy/f2py/f2py2e.py
Executable file
@ -0,0 +1,787 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
|
||||
f2py2e - Fortran to Python C/API generator. 2nd Edition.
|
||||
See __usage__ below.
|
||||
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
Permission to use, modify, and distribute this software is given under the
|
||||
terms of the NumPy License.
|
||||
|
||||
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import pprint
|
||||
import re
|
||||
from pathlib import Path
|
||||
from itertools import dropwhile
|
||||
import argparse
|
||||
import copy
|
||||
|
||||
from . import crackfortran
|
||||
from . import rules
|
||||
from . import cb_rules
|
||||
from . import auxfuncs
|
||||
from . import cfuncs
|
||||
from . import f90mod_rules
|
||||
from . import __version__
|
||||
from . import capi_maps
|
||||
from .cfuncs import errmess
|
||||
from numpy.f2py._backends import f2py_build_generator
|
||||
|
||||
f2py_version = __version__.version
|
||||
numpy_version = __version__.version
|
||||
|
||||
# outmess=sys.stdout.write
|
||||
show = pprint.pprint
|
||||
outmess = auxfuncs.outmess
|
||||
MESON_ONLY_VER = (sys.version_info >= (3, 12))
|
||||
|
||||
__usage__ =\
|
||||
f"""Usage:
|
||||
|
||||
1) To construct extension module sources:
|
||||
|
||||
f2py [<options>] <fortran files> [[[only:]||[skip:]] \\
|
||||
<fortran functions> ] \\
|
||||
[: <fortran files> ...]
|
||||
|
||||
2) To compile fortran files and build extension modules:
|
||||
|
||||
f2py -c [<options>, <build_flib options>, <extra options>] <fortran files>
|
||||
|
||||
3) To generate signature files:
|
||||
|
||||
f2py -h <filename.pyf> ...< same options as in (1) >
|
||||
|
||||
Description: This program generates a Python C/API file (<modulename>module.c)
|
||||
that contains wrappers for given fortran functions so that they
|
||||
can be called from Python. With the -c option the corresponding
|
||||
extension modules are built.
|
||||
|
||||
Options:
|
||||
|
||||
-h <filename> Write signatures of the fortran routines to file <filename>
|
||||
and exit. You can then edit <filename> and use it instead
|
||||
of <fortran files>. If <filename>==stdout then the
|
||||
signatures are printed to stdout.
|
||||
<fortran functions> Names of fortran routines for which Python C/API
|
||||
functions will be generated. Default is all that are found
|
||||
in <fortran files>.
|
||||
<fortran files> Paths to fortran/signature files that will be scanned for
|
||||
<fortran functions> in order to determine their signatures.
|
||||
skip: Ignore fortran functions that follow until `:'.
|
||||
only: Use only fortran functions that follow until `:'.
|
||||
: Get back to <fortran files> mode.
|
||||
|
||||
-m <modulename> Name of the module; f2py generates a Python/C API
|
||||
file <modulename>module.c or extension module <modulename>.
|
||||
Default is 'untitled'.
|
||||
|
||||
'-include<header>' Writes additional headers in the C wrapper, can be passed
|
||||
multiple times, generates #include <header> each time.
|
||||
|
||||
--[no-]lower Do [not] lower the cases in <fortran files>. By default,
|
||||
--lower is assumed with -h key, and --no-lower without -h key.
|
||||
|
||||
--build-dir <dirname> All f2py generated files are created in <dirname>.
|
||||
Default is tempfile.mkdtemp().
|
||||
|
||||
--overwrite-signature Overwrite existing signature file.
|
||||
|
||||
--[no-]latex-doc Create (or not) <modulename>module.tex.
|
||||
Default is --no-latex-doc.
|
||||
--short-latex Create 'incomplete' LaTeX document (without commands
|
||||
\\documentclass, \\tableofcontents, and \\begin{{document}},
|
||||
\\end{{document}}).
|
||||
|
||||
--[no-]rest-doc Create (or not) <modulename>module.rst.
|
||||
Default is --no-rest-doc.
|
||||
|
||||
--debug-capi Create C/API code that reports the state of the wrappers
|
||||
during runtime. Useful for debugging.
|
||||
|
||||
--[no-]wrap-functions Create Fortran subroutine wrappers to Fortran 77
|
||||
functions. --wrap-functions is default because it ensures
|
||||
maximum portability/compiler independence.
|
||||
|
||||
--[no-]freethreading-compatible Create a module that declares it does or
|
||||
doesn't require the GIL. The default is
|
||||
--freethreading-compatible for backward
|
||||
compatibility. Inspect the Fortran code you are wrapping for
|
||||
thread safety issues before passing
|
||||
--no-freethreading-compatible, as f2py does not analyze
|
||||
fortran code for thread safety issues.
|
||||
|
||||
--include-paths <path1>:<path2>:... Search include files from the given
|
||||
directories.
|
||||
|
||||
--help-link [..] List system resources found by system_info.py. See also
|
||||
--link-<resource> switch below. [..] is optional list
|
||||
of resources names. E.g. try 'f2py --help-link lapack_opt'.
|
||||
|
||||
--f2cmap <filename> Load Fortran-to-Python KIND specification from the given
|
||||
file. Default: .f2py_f2cmap in current directory.
|
||||
|
||||
--quiet Run quietly.
|
||||
--verbose Run with extra verbosity.
|
||||
--skip-empty-wrappers Only generate wrapper files when needed.
|
||||
-v Print f2py version ID and exit.
|
||||
|
||||
|
||||
build backend options (only effective with -c)
|
||||
[NO_MESON] is used to indicate an option not meant to be used
|
||||
with the meson backend or above Python 3.12:
|
||||
|
||||
--fcompiler= Specify Fortran compiler type by vendor [NO_MESON]
|
||||
--compiler= Specify distutils C compiler type [NO_MESON]
|
||||
|
||||
--help-fcompiler List available Fortran compilers and exit [NO_MESON]
|
||||
--f77exec= Specify the path to F77 compiler [NO_MESON]
|
||||
--f90exec= Specify the path to F90 compiler [NO_MESON]
|
||||
--f77flags= Specify F77 compiler flags
|
||||
--f90flags= Specify F90 compiler flags
|
||||
--opt= Specify optimization flags [NO_MESON]
|
||||
--arch= Specify architecture specific optimization flags [NO_MESON]
|
||||
--noopt Compile without optimization [NO_MESON]
|
||||
--noarch Compile without arch-dependent optimization [NO_MESON]
|
||||
--debug Compile with debugging information
|
||||
|
||||
--dep <dependency>
|
||||
Specify a meson dependency for the module. This may
|
||||
be passed multiple times for multiple dependencies.
|
||||
Dependencies are stored in a list for further processing.
|
||||
|
||||
Example: --dep lapack --dep scalapack
|
||||
This will identify "lapack" and "scalapack" as dependencies
|
||||
and remove them from argv, leaving a dependencies list
|
||||
containing ["lapack", "scalapack"].
|
||||
|
||||
--backend <backend_type>
|
||||
Specify the build backend for the compilation process.
|
||||
The supported backends are 'meson' and 'distutils'.
|
||||
If not specified, defaults to 'distutils'. On
|
||||
Python 3.12 or higher, the default is 'meson'.
|
||||
|
||||
Extra options (only effective with -c):
|
||||
|
||||
--link-<resource> Link extension module with <resource> as defined
|
||||
by numpy.distutils/system_info.py. E.g. to link
|
||||
with optimized LAPACK libraries (vecLib on MacOSX,
|
||||
ATLAS elsewhere), use --link-lapack_opt.
|
||||
See also --help-link switch. [NO_MESON]
|
||||
|
||||
-L/path/to/lib/ -l<libname>
|
||||
-D<define> -U<name>
|
||||
-I/path/to/include/
|
||||
<filename>.o <filename>.so <filename>.a
|
||||
|
||||
Using the following macros may be required with non-gcc Fortran
|
||||
compilers:
|
||||
-DPREPEND_FORTRAN -DNO_APPEND_FORTRAN -DUPPERCASE_FORTRAN
|
||||
|
||||
When using -DF2PY_REPORT_ATEXIT, a performance report of F2PY
|
||||
interface is printed out at exit (platforms: Linux).
|
||||
|
||||
When using -DF2PY_REPORT_ON_ARRAY_COPY=<int>, a message is
|
||||
sent to stderr whenever F2PY interface makes a copy of an
|
||||
array. Integer <int> sets the threshold for array sizes when
|
||||
a message should be shown.
|
||||
|
||||
Version: {f2py_version}
|
||||
numpy Version: {numpy_version}
|
||||
License: NumPy license (see LICENSE.txt in the NumPy source code)
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
https://numpy.org/doc/stable/f2py/index.html\n"""
|
||||
|
||||
|
||||
def scaninputline(inputline):
|
||||
files, skipfuncs, onlyfuncs, debug = [], [], [], []
|
||||
f, f2, f3, f5, f6, f8, f9, f10 = 1, 0, 0, 0, 0, 0, 0, 0
|
||||
verbose = 1
|
||||
emptygen = True
|
||||
dolc = -1
|
||||
dolatexdoc = 0
|
||||
dorestdoc = 0
|
||||
wrapfuncs = 1
|
||||
buildpath = '.'
|
||||
include_paths, freethreading_compatible, inputline = get_newer_options(inputline)
|
||||
signsfile, modulename = None, None
|
||||
options = {'buildpath': buildpath,
|
||||
'coutput': None,
|
||||
'f2py_wrapper_output': None}
|
||||
for l in inputline:
|
||||
if l == '':
|
||||
pass
|
||||
elif l == 'only:':
|
||||
f = 0
|
||||
elif l == 'skip:':
|
||||
f = -1
|
||||
elif l == ':':
|
||||
f = 1
|
||||
elif l[:8] == '--debug-':
|
||||
debug.append(l[8:])
|
||||
elif l == '--lower':
|
||||
dolc = 1
|
||||
elif l == '--build-dir':
|
||||
f6 = 1
|
||||
elif l == '--no-lower':
|
||||
dolc = 0
|
||||
elif l == '--quiet':
|
||||
verbose = 0
|
||||
elif l == '--verbose':
|
||||
verbose += 1
|
||||
elif l == '--latex-doc':
|
||||
dolatexdoc = 1
|
||||
elif l == '--no-latex-doc':
|
||||
dolatexdoc = 0
|
||||
elif l == '--rest-doc':
|
||||
dorestdoc = 1
|
||||
elif l == '--no-rest-doc':
|
||||
dorestdoc = 0
|
||||
elif l == '--wrap-functions':
|
||||
wrapfuncs = 1
|
||||
elif l == '--no-wrap-functions':
|
||||
wrapfuncs = 0
|
||||
elif l == '--short-latex':
|
||||
options['shortlatex'] = 1
|
||||
elif l == '--coutput':
|
||||
f8 = 1
|
||||
elif l == '--f2py-wrapper-output':
|
||||
f9 = 1
|
||||
elif l == '--f2cmap':
|
||||
f10 = 1
|
||||
elif l == '--overwrite-signature':
|
||||
options['h-overwrite'] = 1
|
||||
elif l == '-h':
|
||||
f2 = 1
|
||||
elif l == '-m':
|
||||
f3 = 1
|
||||
elif l[:2] == '-v':
|
||||
print(f2py_version)
|
||||
sys.exit()
|
||||
elif l == '--show-compilers':
|
||||
f5 = 1
|
||||
elif l[:8] == '-include':
|
||||
cfuncs.outneeds['userincludes'].append(l[9:-1])
|
||||
cfuncs.userincludes[l[9:-1]] = '#include ' + l[8:]
|
||||
elif l == '--skip-empty-wrappers':
|
||||
emptygen = False
|
||||
elif l[0] == '-':
|
||||
errmess('Unknown option %s\n' % repr(l))
|
||||
sys.exit()
|
||||
elif f2:
|
||||
f2 = 0
|
||||
signsfile = l
|
||||
elif f3:
|
||||
f3 = 0
|
||||
modulename = l
|
||||
elif f6:
|
||||
f6 = 0
|
||||
buildpath = l
|
||||
elif f8:
|
||||
f8 = 0
|
||||
options["coutput"] = l
|
||||
elif f9:
|
||||
f9 = 0
|
||||
options["f2py_wrapper_output"] = l
|
||||
elif f10:
|
||||
f10 = 0
|
||||
options["f2cmap_file"] = l
|
||||
elif f == 1:
|
||||
try:
|
||||
with open(l):
|
||||
pass
|
||||
files.append(l)
|
||||
except OSError as detail:
|
||||
errmess(f'OSError: {detail!s}. Skipping file "{l!s}".\n')
|
||||
elif f == -1:
|
||||
skipfuncs.append(l)
|
||||
elif f == 0:
|
||||
onlyfuncs.append(l)
|
||||
if not f5 and not files and not modulename:
|
||||
print(__usage__)
|
||||
sys.exit()
|
||||
if not os.path.isdir(buildpath):
|
||||
if not verbose:
|
||||
outmess('Creating build directory %s\n' % (buildpath))
|
||||
os.mkdir(buildpath)
|
||||
if signsfile:
|
||||
signsfile = os.path.join(buildpath, signsfile)
|
||||
if signsfile and os.path.isfile(signsfile) and 'h-overwrite' not in options:
|
||||
errmess(
|
||||
'Signature file "%s" exists!!! Use --overwrite-signature to overwrite.\n' % (signsfile))
|
||||
sys.exit()
|
||||
|
||||
options['emptygen'] = emptygen
|
||||
options['debug'] = debug
|
||||
options['verbose'] = verbose
|
||||
if dolc == -1 and not signsfile:
|
||||
options['do-lower'] = 0
|
||||
else:
|
||||
options['do-lower'] = dolc
|
||||
if modulename:
|
||||
options['module'] = modulename
|
||||
if signsfile:
|
||||
options['signsfile'] = signsfile
|
||||
if onlyfuncs:
|
||||
options['onlyfuncs'] = onlyfuncs
|
||||
if skipfuncs:
|
||||
options['skipfuncs'] = skipfuncs
|
||||
options['dolatexdoc'] = dolatexdoc
|
||||
options['dorestdoc'] = dorestdoc
|
||||
options['wrapfuncs'] = wrapfuncs
|
||||
options['buildpath'] = buildpath
|
||||
options['include_paths'] = include_paths
|
||||
options['requires_gil'] = not freethreading_compatible
|
||||
options.setdefault('f2cmap_file', None)
|
||||
return files, options
|
||||
|
||||
|
||||
def callcrackfortran(files, options):
|
||||
rules.options = options
|
||||
crackfortran.debug = options['debug']
|
||||
crackfortran.verbose = options['verbose']
|
||||
if 'module' in options:
|
||||
crackfortran.f77modulename = options['module']
|
||||
if 'skipfuncs' in options:
|
||||
crackfortran.skipfuncs = options['skipfuncs']
|
||||
if 'onlyfuncs' in options:
|
||||
crackfortran.onlyfuncs = options['onlyfuncs']
|
||||
crackfortran.include_paths[:] = options['include_paths']
|
||||
crackfortran.dolowercase = options['do-lower']
|
||||
postlist = crackfortran.crackfortran(files)
|
||||
if 'signsfile' in options:
|
||||
outmess('Saving signatures to file "%s"\n' % (options['signsfile']))
|
||||
pyf = crackfortran.crack2fortran(postlist)
|
||||
if options['signsfile'][-6:] == 'stdout':
|
||||
sys.stdout.write(pyf)
|
||||
else:
|
||||
with open(options['signsfile'], 'w') as f:
|
||||
f.write(pyf)
|
||||
if options["coutput"] is None:
|
||||
for mod in postlist:
|
||||
mod["coutput"] = "%smodule.c" % mod["name"]
|
||||
else:
|
||||
for mod in postlist:
|
||||
mod["coutput"] = options["coutput"]
|
||||
if options["f2py_wrapper_output"] is None:
|
||||
for mod in postlist:
|
||||
mod["f2py_wrapper_output"] = "%s-f2pywrappers.f" % mod["name"]
|
||||
else:
|
||||
for mod in postlist:
|
||||
mod["f2py_wrapper_output"] = options["f2py_wrapper_output"]
|
||||
for mod in postlist:
|
||||
if options["requires_gil"]:
|
||||
mod['gil_used'] = 'Py_MOD_GIL_USED'
|
||||
else:
|
||||
mod['gil_used'] = 'Py_MOD_GIL_NOT_USED'
|
||||
return postlist
|
||||
|
||||
|
||||
def buildmodules(lst):
|
||||
cfuncs.buildcfuncs()
|
||||
outmess('Building modules...\n')
|
||||
modules, mnames, isusedby = [], [], {}
|
||||
for item in lst:
|
||||
if '__user__' in item['name']:
|
||||
cb_rules.buildcallbacks(item)
|
||||
else:
|
||||
if 'use' in item:
|
||||
for u in item['use'].keys():
|
||||
if u not in isusedby:
|
||||
isusedby[u] = []
|
||||
isusedby[u].append(item['name'])
|
||||
modules.append(item)
|
||||
mnames.append(item['name'])
|
||||
ret = {}
|
||||
for module, name in zip(modules, mnames):
|
||||
if name in isusedby:
|
||||
outmess('\tSkipping module "%s" which is used by %s.\n' % (
|
||||
name, ','.join('"%s"' % s for s in isusedby[name])))
|
||||
else:
|
||||
um = []
|
||||
if 'use' in module:
|
||||
for u in module['use'].keys():
|
||||
if u in isusedby and u in mnames:
|
||||
um.append(modules[mnames.index(u)])
|
||||
else:
|
||||
outmess(
|
||||
f'\tModule "{name}" uses nonexisting "{u}" '
|
||||
'which will be ignored.\n')
|
||||
ret[name] = {}
|
||||
dict_append(ret[name], rules.buildmodule(module, um))
|
||||
return ret
|
||||
|
||||
|
||||
def dict_append(d_out, d_in):
|
||||
for (k, v) in d_in.items():
|
||||
if k not in d_out:
|
||||
d_out[k] = []
|
||||
if isinstance(v, list):
|
||||
d_out[k] = d_out[k] + v
|
||||
else:
|
||||
d_out[k].append(v)
|
||||
|
||||
|
||||
def run_main(comline_list):
|
||||
"""
|
||||
Equivalent to running::
|
||||
|
||||
f2py <args>
|
||||
|
||||
where ``<args>=string.join(<list>,' ')``, but in Python. Unless
|
||||
``-h`` is used, this function returns a dictionary containing
|
||||
information on generated modules and their dependencies on source
|
||||
files.
|
||||
|
||||
You cannot build extension modules with this function, that is,
|
||||
using ``-c`` is not allowed. Use the ``compile`` command instead.
|
||||
|
||||
Examples
|
||||
--------
|
||||
The command ``f2py -m scalar scalar.f`` can be executed from Python as
|
||||
follows.
|
||||
|
||||
.. literalinclude:: ../../source/f2py/code/results/run_main_session.dat
|
||||
:language: python
|
||||
|
||||
"""
|
||||
crackfortran.reset_global_f2py_vars()
|
||||
f2pydir = os.path.dirname(os.path.abspath(cfuncs.__file__))
|
||||
fobjhsrc = os.path.join(f2pydir, 'src', 'fortranobject.h')
|
||||
fobjcsrc = os.path.join(f2pydir, 'src', 'fortranobject.c')
|
||||
# gh-22819 -- begin
|
||||
parser = make_f2py_compile_parser()
|
||||
args, comline_list = parser.parse_known_args(comline_list)
|
||||
pyf_files, _ = filter_files("", "[.]pyf([.]src|)", comline_list)
|
||||
# Checks that no existing modulename is defined in a pyf file
|
||||
# TODO: Remove all this when scaninputline is replaced
|
||||
if args.module_name:
|
||||
if "-h" in comline_list:
|
||||
modname = (
|
||||
args.module_name
|
||||
) # Directly use from args when -h is present
|
||||
else:
|
||||
modname = validate_modulename(
|
||||
pyf_files, args.module_name
|
||||
) # Validate modname when -h is not present
|
||||
comline_list += ['-m', modname] # needed for the rest of scaninputline
|
||||
# gh-22819 -- end
|
||||
files, options = scaninputline(comline_list)
|
||||
auxfuncs.options = options
|
||||
capi_maps.load_f2cmap_file(options['f2cmap_file'])
|
||||
postlist = callcrackfortran(files, options)
|
||||
isusedby = {}
|
||||
for plist in postlist:
|
||||
if 'use' in plist:
|
||||
for u in plist['use'].keys():
|
||||
if u not in isusedby:
|
||||
isusedby[u] = []
|
||||
isusedby[u].append(plist['name'])
|
||||
for plist in postlist:
|
||||
if plist['block'] == 'python module' and '__user__' in plist['name']:
|
||||
if plist['name'] in isusedby:
|
||||
# if not quiet:
|
||||
outmess(
|
||||
f'Skipping Makefile build for module "{plist["name"]}" '
|
||||
'which is used by {}\n'.format(
|
||||
','.join(f'"{s}"' for s in isusedby[plist['name']])))
|
||||
if 'signsfile' in options:
|
||||
if options['verbose'] > 1:
|
||||
outmess(
|
||||
'Stopping. Edit the signature file and then run f2py on the signature file: ')
|
||||
outmess('%s %s\n' %
|
||||
(os.path.basename(sys.argv[0]), options['signsfile']))
|
||||
return
|
||||
for plist in postlist:
|
||||
if plist['block'] != 'python module':
|
||||
if 'python module' not in options:
|
||||
errmess(
|
||||
'Tip: If your original code is Fortran source then you must use -m option.\n')
|
||||
raise TypeError('All blocks must be python module blocks but got %s' % (
|
||||
repr(plist['block'])))
|
||||
auxfuncs.debugoptions = options['debug']
|
||||
f90mod_rules.options = options
|
||||
auxfuncs.wrapfuncs = options['wrapfuncs']
|
||||
|
||||
ret = buildmodules(postlist)
|
||||
|
||||
for mn in ret.keys():
|
||||
dict_append(ret[mn], {'csrc': fobjcsrc, 'h': fobjhsrc})
|
||||
return ret
|
||||
|
||||
|
||||
def filter_files(prefix, suffix, files, remove_prefix=None):
|
||||
"""
|
||||
Filter files by prefix and suffix.
|
||||
"""
|
||||
filtered, rest = [], []
|
||||
match = re.compile(prefix + r'.*' + suffix + r'\Z').match
|
||||
if remove_prefix:
|
||||
ind = len(prefix)
|
||||
else:
|
||||
ind = 0
|
||||
for file in [x.strip() for x in files]:
|
||||
if match(file):
|
||||
filtered.append(file[ind:])
|
||||
else:
|
||||
rest.append(file)
|
||||
return filtered, rest
|
||||
|
||||
|
||||
def get_prefix(module):
|
||||
p = os.path.dirname(os.path.dirname(module.__file__))
|
||||
return p
|
||||
|
||||
|
||||
class CombineIncludePaths(argparse.Action):
|
||||
def __call__(self, parser, namespace, values, option_string=None):
|
||||
include_paths_set = set(getattr(namespace, 'include_paths', []) or [])
|
||||
if option_string == "--include_paths":
|
||||
outmess("Use --include-paths or -I instead of --include_paths which will be removed")
|
||||
if option_string == "--include-paths" or option_string == "--include_paths":
|
||||
include_paths_set.update(values.split(':'))
|
||||
else:
|
||||
include_paths_set.add(values)
|
||||
setattr(namespace, 'include_paths', list(include_paths_set))
|
||||
|
||||
def f2py_parser():
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
parser.add_argument("-I", dest="include_paths", action=CombineIncludePaths)
|
||||
parser.add_argument("--include-paths", dest="include_paths", action=CombineIncludePaths)
|
||||
parser.add_argument("--include_paths", dest="include_paths", action=CombineIncludePaths)
|
||||
parser.add_argument("--freethreading-compatible", dest="ftcompat", action=argparse.BooleanOptionalAction)
|
||||
return parser
|
||||
|
||||
def get_newer_options(iline):
|
||||
iline = (' '.join(iline)).split()
|
||||
parser = f2py_parser()
|
||||
args, remain = parser.parse_known_args(iline)
|
||||
ipaths = args.include_paths
|
||||
if args.include_paths is None:
|
||||
ipaths = []
|
||||
return ipaths, args.ftcompat, remain
|
||||
|
||||
def make_f2py_compile_parser():
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
parser.add_argument("--dep", action="append", dest="dependencies")
|
||||
parser.add_argument("--backend", choices=['meson', 'distutils'], default='distutils')
|
||||
parser.add_argument("-m", dest="module_name")
|
||||
return parser
|
||||
|
||||
def preparse_sysargv():
|
||||
# To keep backwards bug compatibility, newer flags are handled by argparse,
|
||||
# and `sys.argv` is passed to the rest of `f2py` as is.
|
||||
parser = make_f2py_compile_parser()
|
||||
|
||||
args, remaining_argv = parser.parse_known_args()
|
||||
sys.argv = [sys.argv[0]] + remaining_argv
|
||||
|
||||
backend_key = args.backend
|
||||
if MESON_ONLY_VER and backend_key == 'distutils':
|
||||
outmess("Cannot use distutils backend with Python>=3.12,"
|
||||
" using meson backend instead.\n")
|
||||
backend_key = "meson"
|
||||
|
||||
return {
|
||||
"dependencies": args.dependencies or [],
|
||||
"backend": backend_key,
|
||||
"modulename": args.module_name,
|
||||
}
|
||||
|
||||
def run_compile():
|
||||
"""
|
||||
Do it all in one call!
|
||||
"""
|
||||
import tempfile
|
||||
|
||||
# Collect dependency flags, preprocess sys.argv
|
||||
argy = preparse_sysargv()
|
||||
modulename = argy["modulename"]
|
||||
if modulename is None:
|
||||
modulename = 'untitled'
|
||||
dependencies = argy["dependencies"]
|
||||
backend_key = argy["backend"]
|
||||
build_backend = f2py_build_generator(backend_key)
|
||||
|
||||
i = sys.argv.index('-c')
|
||||
del sys.argv[i]
|
||||
|
||||
remove_build_dir = 0
|
||||
try:
|
||||
i = sys.argv.index('--build-dir')
|
||||
except ValueError:
|
||||
i = None
|
||||
if i is not None:
|
||||
build_dir = sys.argv[i + 1]
|
||||
del sys.argv[i + 1]
|
||||
del sys.argv[i]
|
||||
else:
|
||||
remove_build_dir = 1
|
||||
build_dir = tempfile.mkdtemp()
|
||||
|
||||
_reg1 = re.compile(r'--link-')
|
||||
sysinfo_flags = [_m for _m in sys.argv[1:] if _reg1.match(_m)]
|
||||
sys.argv = [_m for _m in sys.argv if _m not in sysinfo_flags]
|
||||
if sysinfo_flags:
|
||||
sysinfo_flags = [f[7:] for f in sysinfo_flags]
|
||||
|
||||
_reg2 = re.compile(
|
||||
r'--((no-|)(wrap-functions|lower|freethreading-compatible)|debug-capi|quiet|skip-empty-wrappers)|-include')
|
||||
f2py_flags = [_m for _m in sys.argv[1:] if _reg2.match(_m)]
|
||||
sys.argv = [_m for _m in sys.argv if _m not in f2py_flags]
|
||||
f2py_flags2 = []
|
||||
fl = 0
|
||||
for a in sys.argv[1:]:
|
||||
if a in ['only:', 'skip:']:
|
||||
fl = 1
|
||||
elif a == ':':
|
||||
fl = 0
|
||||
if fl or a == ':':
|
||||
f2py_flags2.append(a)
|
||||
if f2py_flags2 and f2py_flags2[-1] != ':':
|
||||
f2py_flags2.append(':')
|
||||
f2py_flags.extend(f2py_flags2)
|
||||
sys.argv = [_m for _m in sys.argv if _m not in f2py_flags2]
|
||||
_reg3 = re.compile(
|
||||
r'--((f(90)?compiler(-exec|)|compiler)=|help-compiler)')
|
||||
flib_flags = [_m for _m in sys.argv[1:] if _reg3.match(_m)]
|
||||
sys.argv = [_m for _m in sys.argv if _m not in flib_flags]
|
||||
# TODO: Once distutils is dropped completely, i.e. min_ver >= 3.12, unify into --fflags
|
||||
reg_f77_f90_flags = re.compile(r'--f(77|90)flags=')
|
||||
reg_distutils_flags = re.compile(r'--((f(77|90)exec|opt|arch)=|(debug|noopt|noarch|help-fcompiler))')
|
||||
fc_flags = [_m for _m in sys.argv[1:] if reg_f77_f90_flags.match(_m)]
|
||||
distutils_flags = [_m for _m in sys.argv[1:] if reg_distutils_flags.match(_m)]
|
||||
if not (MESON_ONLY_VER or backend_key == 'meson'):
|
||||
fc_flags.extend(distutils_flags)
|
||||
sys.argv = [_m for _m in sys.argv if _m not in (fc_flags + distutils_flags)]
|
||||
|
||||
del_list = []
|
||||
for s in flib_flags:
|
||||
v = '--fcompiler='
|
||||
if s[:len(v)] == v:
|
||||
if MESON_ONLY_VER or backend_key == 'meson':
|
||||
outmess(
|
||||
"--fcompiler cannot be used with meson,"
|
||||
"set compiler with the FC environment variable\n"
|
||||
)
|
||||
else:
|
||||
from numpy.distutils import fcompiler
|
||||
fcompiler.load_all_fcompiler_classes()
|
||||
allowed_keys = list(fcompiler.fcompiler_class.keys())
|
||||
nv = ov = s[len(v):].lower()
|
||||
if ov not in allowed_keys:
|
||||
vmap = {} # XXX
|
||||
try:
|
||||
nv = vmap[ov]
|
||||
except KeyError:
|
||||
if ov not in vmap.values():
|
||||
print('Unknown vendor: "%s"' % (s[len(v):]))
|
||||
nv = ov
|
||||
i = flib_flags.index(s)
|
||||
flib_flags[i] = '--fcompiler=' + nv
|
||||
continue
|
||||
for s in del_list:
|
||||
i = flib_flags.index(s)
|
||||
del flib_flags[i]
|
||||
assert len(flib_flags) <= 2, repr(flib_flags)
|
||||
|
||||
_reg5 = re.compile(r'--(verbose)')
|
||||
setup_flags = [_m for _m in sys.argv[1:] if _reg5.match(_m)]
|
||||
sys.argv = [_m for _m in sys.argv if _m not in setup_flags]
|
||||
|
||||
if '--quiet' in f2py_flags:
|
||||
setup_flags.append('--quiet')
|
||||
|
||||
# Ugly filter to remove everything but sources
|
||||
sources = sys.argv[1:]
|
||||
f2cmapopt = '--f2cmap'
|
||||
if f2cmapopt in sys.argv:
|
||||
i = sys.argv.index(f2cmapopt)
|
||||
f2py_flags.extend(sys.argv[i:i + 2])
|
||||
del sys.argv[i + 1], sys.argv[i]
|
||||
sources = sys.argv[1:]
|
||||
|
||||
pyf_files, _sources = filter_files("", "[.]pyf([.]src|)", sources)
|
||||
sources = pyf_files + _sources
|
||||
modulename = validate_modulename(pyf_files, modulename)
|
||||
extra_objects, sources = filter_files('', '[.](o|a|so|dylib)', sources)
|
||||
library_dirs, sources = filter_files('-L', '', sources, remove_prefix=1)
|
||||
libraries, sources = filter_files('-l', '', sources, remove_prefix=1)
|
||||
undef_macros, sources = filter_files('-U', '', sources, remove_prefix=1)
|
||||
define_macros, sources = filter_files('-D', '', sources, remove_prefix=1)
|
||||
for i in range(len(define_macros)):
|
||||
name_value = define_macros[i].split('=', 1)
|
||||
if len(name_value) == 1:
|
||||
name_value.append(None)
|
||||
if len(name_value) == 2:
|
||||
define_macros[i] = tuple(name_value)
|
||||
else:
|
||||
print('Invalid use of -D:', name_value)
|
||||
|
||||
# Construct wrappers / signatures / things
|
||||
if backend_key == 'meson':
|
||||
if not pyf_files:
|
||||
outmess('Using meson backend\nWill pass --lower to f2py\nSee https://numpy.org/doc/stable/f2py/buildtools/meson.html\n')
|
||||
f2py_flags.append('--lower')
|
||||
run_main(f" {' '.join(f2py_flags)} -m {modulename} {' '.join(sources)}".split())
|
||||
else:
|
||||
run_main(f" {' '.join(f2py_flags)} {' '.join(pyf_files)}".split())
|
||||
|
||||
# Order matters here, includes are needed for run_main above
|
||||
include_dirs, _, sources = get_newer_options(sources)
|
||||
# Now use the builder
|
||||
builder = build_backend(
|
||||
modulename,
|
||||
sources,
|
||||
extra_objects,
|
||||
build_dir,
|
||||
include_dirs,
|
||||
library_dirs,
|
||||
libraries,
|
||||
define_macros,
|
||||
undef_macros,
|
||||
f2py_flags,
|
||||
sysinfo_flags,
|
||||
fc_flags,
|
||||
flib_flags,
|
||||
setup_flags,
|
||||
remove_build_dir,
|
||||
{"dependencies": dependencies},
|
||||
)
|
||||
|
||||
builder.compile()
|
||||
|
||||
|
||||
def validate_modulename(pyf_files, modulename='untitled'):
|
||||
if len(pyf_files) > 1:
|
||||
raise ValueError("Only one .pyf file per call")
|
||||
if pyf_files:
|
||||
pyff = pyf_files[0]
|
||||
pyf_modname = auxfuncs.get_f2py_modulename(pyff)
|
||||
if modulename != pyf_modname:
|
||||
outmess(
|
||||
f"Ignoring -m {modulename}.\n"
|
||||
f"{pyff} defines {pyf_modname} to be the modulename.\n"
|
||||
)
|
||||
modulename = pyf_modname
|
||||
return modulename
|
||||
|
||||
def main():
|
||||
if '--help-link' in sys.argv[1:]:
|
||||
sys.argv.remove('--help-link')
|
||||
if MESON_ONLY_VER:
|
||||
outmess("Use --dep for meson builds\n")
|
||||
else:
|
||||
from numpy.distutils.system_info import show_all
|
||||
show_all()
|
||||
return
|
||||
|
||||
if '-c' in sys.argv[1:]:
|
||||
run_compile()
|
||||
else:
|
||||
run_main(sys.argv[1:])
|
272
lib/python3.13/site-packages/numpy/f2py/f90mod_rules.py
Normal file
272
lib/python3.13/site-packages/numpy/f2py/f90mod_rules.py
Normal file
@ -0,0 +1,272 @@
|
||||
"""
|
||||
Build F90 module support for f2py2e.
|
||||
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
Permission to use, modify, and distribute this software is given under the
|
||||
terms of the NumPy License.
|
||||
|
||||
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
"""
|
||||
__version__ = "$Revision: 1.27 $"[10:-1]
|
||||
|
||||
f2py_version = 'See `f2py -v`'
|
||||
|
||||
import numpy as np
|
||||
|
||||
from . import capi_maps
|
||||
from . import func2subr
|
||||
from .crackfortran import undo_rmbadname, undo_rmbadname1
|
||||
|
||||
# The environment provided by auxfuncs.py is needed for some calls to eval.
|
||||
# As the needed functions cannot be determined by static inspection of the
|
||||
# code, it is safest to use import * pending a major refactoring of f2py.
|
||||
from .auxfuncs import *
|
||||
|
||||
options = {}
|
||||
|
||||
|
||||
def findf90modules(m):
|
||||
if ismodule(m):
|
||||
return [m]
|
||||
if not hasbody(m):
|
||||
return []
|
||||
ret = []
|
||||
for b in m['body']:
|
||||
if ismodule(b):
|
||||
ret.append(b)
|
||||
else:
|
||||
ret = ret + findf90modules(b)
|
||||
return ret
|
||||
|
||||
fgetdims1 = """\
|
||||
external f2pysetdata
|
||||
logical ns
|
||||
integer r,i
|
||||
integer(%d) s(*)
|
||||
ns = .FALSE.
|
||||
if (allocated(d)) then
|
||||
do i=1,r
|
||||
if ((size(d,i).ne.s(i)).and.(s(i).ge.0)) then
|
||||
ns = .TRUE.
|
||||
end if
|
||||
end do
|
||||
if (ns) then
|
||||
deallocate(d)
|
||||
end if
|
||||
end if
|
||||
if ((.not.allocated(d)).and.(s(1).ge.1)) then""" % np.intp().itemsize
|
||||
|
||||
fgetdims2 = """\
|
||||
end if
|
||||
if (allocated(d)) then
|
||||
do i=1,r
|
||||
s(i) = size(d,i)
|
||||
end do
|
||||
end if
|
||||
flag = 1
|
||||
call f2pysetdata(d,allocated(d))"""
|
||||
|
||||
fgetdims2_sa = """\
|
||||
end if
|
||||
if (allocated(d)) then
|
||||
do i=1,r
|
||||
s(i) = size(d,i)
|
||||
end do
|
||||
!s(r) must be equal to len(d(1))
|
||||
end if
|
||||
flag = 2
|
||||
call f2pysetdata(d,allocated(d))"""
|
||||
|
||||
|
||||
def buildhooks(pymod):
|
||||
from . import rules
|
||||
ret = {'f90modhooks': [], 'initf90modhooks': [], 'body': [],
|
||||
'need': ['F_FUNC', 'arrayobject.h'],
|
||||
'separatorsfor': {'includes0': '\n', 'includes': '\n'},
|
||||
'docs': ['"Fortran 90/95 modules:\\n"'],
|
||||
'latexdoc': []}
|
||||
fhooks = ['']
|
||||
|
||||
def fadd(line, s=fhooks):
|
||||
s[0] = '%s\n %s' % (s[0], line)
|
||||
doc = ['']
|
||||
|
||||
def dadd(line, s=doc):
|
||||
s[0] = '%s\n%s' % (s[0], line)
|
||||
|
||||
usenames = getuseblocks(pymod)
|
||||
for m in findf90modules(pymod):
|
||||
contains_functions_or_subroutines = any(
|
||||
item for item in m["body"] if item["block"] in ["function", "subroutine"]
|
||||
)
|
||||
sargs, fargs, efargs, modobjs, notvars, onlyvars = [], [], [], [], [
|
||||
m['name']], []
|
||||
sargsp = []
|
||||
ifargs = []
|
||||
mfargs = []
|
||||
if hasbody(m):
|
||||
for b in m['body']:
|
||||
notvars.append(b['name'])
|
||||
for n in m['vars'].keys():
|
||||
var = m['vars'][n]
|
||||
|
||||
if (n not in notvars and isvariable(var)) and (not l_or(isintent_hide, isprivate)(var)):
|
||||
onlyvars.append(n)
|
||||
mfargs.append(n)
|
||||
outmess('\t\tConstructing F90 module support for "%s"...\n' %
|
||||
(m['name']))
|
||||
if len(onlyvars) == 0 and len(notvars) == 1 and m['name'] in notvars:
|
||||
outmess(f"\t\t\tSkipping {m['name']} since there are no public vars/func in this module...\n")
|
||||
continue
|
||||
|
||||
if m['name'] in usenames and not contains_functions_or_subroutines:
|
||||
outmess(f"\t\t\tSkipping {m['name']} since it is in 'use'...\n")
|
||||
continue
|
||||
if onlyvars:
|
||||
outmess('\t\t Variables: %s\n' % (' '.join(onlyvars)))
|
||||
chooks = ['']
|
||||
|
||||
def cadd(line, s=chooks):
|
||||
s[0] = '%s\n%s' % (s[0], line)
|
||||
ihooks = ['']
|
||||
|
||||
def iadd(line, s=ihooks):
|
||||
s[0] = '%s\n%s' % (s[0], line)
|
||||
|
||||
vrd = capi_maps.modsign2map(m)
|
||||
cadd('static FortranDataDef f2py_%s_def[] = {' % (m['name']))
|
||||
dadd('\\subsection{Fortran 90/95 module \\texttt{%s}}\n' % (m['name']))
|
||||
if hasnote(m):
|
||||
note = m['note']
|
||||
if isinstance(note, list):
|
||||
note = '\n'.join(note)
|
||||
dadd(note)
|
||||
if onlyvars:
|
||||
dadd('\\begin{description}')
|
||||
for n in onlyvars:
|
||||
var = m['vars'][n]
|
||||
modobjs.append(n)
|
||||
ct = capi_maps.getctype(var)
|
||||
at = capi_maps.c2capi_map[ct]
|
||||
dm = capi_maps.getarrdims(n, var)
|
||||
dms = dm['dims'].replace('*', '-1').strip()
|
||||
dms = dms.replace(':', '-1').strip()
|
||||
if not dms:
|
||||
dms = '-1'
|
||||
use_fgetdims2 = fgetdims2
|
||||
cadd('\t{"%s",%s,{{%s}},%s, %s},' %
|
||||
(undo_rmbadname1(n), dm['rank'], dms, at,
|
||||
capi_maps.get_elsize(var)))
|
||||
dadd('\\item[]{{}\\verb@%s@{}}' %
|
||||
(capi_maps.getarrdocsign(n, var)))
|
||||
if hasnote(var):
|
||||
note = var['note']
|
||||
if isinstance(note, list):
|
||||
note = '\n'.join(note)
|
||||
dadd('--- %s' % (note))
|
||||
if isallocatable(var):
|
||||
fargs.append('f2py_%s_getdims_%s' % (m['name'], n))
|
||||
efargs.append(fargs[-1])
|
||||
sargs.append(
|
||||
'void (*%s)(int*,npy_intp*,void(*)(char*,npy_intp*),int*)' % (n))
|
||||
sargsp.append('void (*)(int*,npy_intp*,void(*)(char*,npy_intp*),int*)')
|
||||
iadd('\tf2py_%s_def[i_f2py++].func = %s;' % (m['name'], n))
|
||||
fadd('subroutine %s(r,s,f2pysetdata,flag)' % (fargs[-1]))
|
||||
fadd('use %s, only: d => %s\n' %
|
||||
(m['name'], undo_rmbadname1(n)))
|
||||
fadd('integer flag\n')
|
||||
fhooks[0] = fhooks[0] + fgetdims1
|
||||
dms = range(1, int(dm['rank']) + 1)
|
||||
fadd(' allocate(d(%s))\n' %
|
||||
(','.join(['s(%s)' % i for i in dms])))
|
||||
fhooks[0] = fhooks[0] + use_fgetdims2
|
||||
fadd('end subroutine %s' % (fargs[-1]))
|
||||
else:
|
||||
fargs.append(n)
|
||||
sargs.append('char *%s' % (n))
|
||||
sargsp.append('char*')
|
||||
iadd('\tf2py_%s_def[i_f2py++].data = %s;' % (m['name'], n))
|
||||
if onlyvars:
|
||||
dadd('\\end{description}')
|
||||
if hasbody(m):
|
||||
for b in m['body']:
|
||||
if not isroutine(b):
|
||||
outmess("f90mod_rules.buildhooks:"
|
||||
f" skipping {b['block']} {b['name']}\n")
|
||||
continue
|
||||
modobjs.append('%s()' % (b['name']))
|
||||
b['modulename'] = m['name']
|
||||
api, wrap = rules.buildapi(b)
|
||||
if isfunction(b):
|
||||
fhooks[0] = fhooks[0] + wrap
|
||||
fargs.append('f2pywrap_%s_%s' % (m['name'], b['name']))
|
||||
ifargs.append(func2subr.createfuncwrapper(b, signature=1))
|
||||
else:
|
||||
if wrap:
|
||||
fhooks[0] = fhooks[0] + wrap
|
||||
fargs.append('f2pywrap_%s_%s' % (m['name'], b['name']))
|
||||
ifargs.append(
|
||||
func2subr.createsubrwrapper(b, signature=1))
|
||||
else:
|
||||
fargs.append(b['name'])
|
||||
mfargs.append(fargs[-1])
|
||||
api['externroutines'] = []
|
||||
ar = applyrules(api, vrd)
|
||||
ar['docs'] = []
|
||||
ar['docshort'] = []
|
||||
ret = dictappend(ret, ar)
|
||||
cadd(('\t{"%s",-1,{{-1}},0,0,NULL,(void *)'
|
||||
'f2py_rout_#modulename#_%s_%s,'
|
||||
'doc_f2py_rout_#modulename#_%s_%s},')
|
||||
% (b['name'], m['name'], b['name'], m['name'], b['name']))
|
||||
sargs.append('char *%s' % (b['name']))
|
||||
sargsp.append('char *')
|
||||
iadd('\tf2py_%s_def[i_f2py++].data = %s;' %
|
||||
(m['name'], b['name']))
|
||||
cadd('\t{NULL}\n};\n')
|
||||
iadd('}')
|
||||
ihooks[0] = 'static void f2py_setup_%s(%s) {\n\tint i_f2py=0;%s' % (
|
||||
m['name'], ','.join(sargs), ihooks[0])
|
||||
if '_' in m['name']:
|
||||
F_FUNC = 'F_FUNC_US'
|
||||
else:
|
||||
F_FUNC = 'F_FUNC'
|
||||
iadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void (*)(%s));'
|
||||
% (F_FUNC, m['name'], m['name'].upper(), ','.join(sargsp)))
|
||||
iadd('static void f2py_init_%s(void) {' % (m['name']))
|
||||
iadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
|
||||
% (F_FUNC, m['name'], m['name'].upper(), m['name']))
|
||||
iadd('}\n')
|
||||
ret['f90modhooks'] = ret['f90modhooks'] + chooks + ihooks
|
||||
ret['initf90modhooks'] = ['\tPyDict_SetItemString(d, "%s", PyFortranObject_New(f2py_%s_def,f2py_init_%s));' % (
|
||||
m['name'], m['name'], m['name'])] + ret['initf90modhooks']
|
||||
fadd('')
|
||||
fadd('subroutine f2pyinit%s(f2pysetupfunc)' % (m['name']))
|
||||
if mfargs:
|
||||
for a in undo_rmbadname(mfargs):
|
||||
fadd('use %s, only : %s' % (m['name'], a))
|
||||
if ifargs:
|
||||
fadd(' '.join(['interface'] + ifargs))
|
||||
fadd('end interface')
|
||||
fadd('external f2pysetupfunc')
|
||||
if efargs:
|
||||
for a in undo_rmbadname(efargs):
|
||||
fadd('external %s' % (a))
|
||||
fadd('call f2pysetupfunc(%s)' % (','.join(undo_rmbadname(fargs))))
|
||||
fadd('end subroutine f2pyinit%s\n' % (m['name']))
|
||||
|
||||
dadd('\n'.join(ret['latexdoc']).replace(
|
||||
r'\subsection{', r'\subsubsection{'))
|
||||
|
||||
ret['latexdoc'] = []
|
||||
ret['docs'].append('"\t%s --- %s"' % (m['name'],
|
||||
','.join(undo_rmbadname(modobjs))))
|
||||
|
||||
ret['routine_defs'] = ''
|
||||
ret['doc'] = []
|
||||
ret['docshort'] = []
|
||||
ret['latexdoc'] = doc[0]
|
||||
if len(ret['docs']) <= 1:
|
||||
ret['docs'] = ''
|
||||
return ret, fhooks[0]
|
323
lib/python3.13/site-packages/numpy/f2py/func2subr.py
Normal file
323
lib/python3.13/site-packages/numpy/f2py/func2subr.py
Normal file
@ -0,0 +1,323 @@
|
||||
"""
|
||||
|
||||
Rules for building C/API module with f2py2e.
|
||||
|
||||
Copyright 1999 -- 2011 Pearu Peterson all rights reserved.
|
||||
Copyright 2011 -- present NumPy Developers.
|
||||
Permission to use, modify, and distribute this software is given under the
|
||||
terms of the NumPy License.
|
||||
|
||||
NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
"""
|
||||
import copy
|
||||
|
||||
from .auxfuncs import (
|
||||
getfortranname, isexternal, isfunction, isfunction_wrap, isintent_in,
|
||||
isintent_out, islogicalfunction, ismoduleroutine, isscalar,
|
||||
issubroutine, issubroutine_wrap, outmess, show
|
||||
)
|
||||
|
||||
from ._isocbind import isoc_kindmap
|
||||
|
||||
def var2fixfortran(vars, a, fa=None, f90mode=None):
|
||||
if fa is None:
|
||||
fa = a
|
||||
if a not in vars:
|
||||
show(vars)
|
||||
outmess('var2fixfortran: No definition for argument "%s".\n' % a)
|
||||
return ''
|
||||
if 'typespec' not in vars[a]:
|
||||
show(vars[a])
|
||||
outmess('var2fixfortran: No typespec for argument "%s".\n' % a)
|
||||
return ''
|
||||
vardef = vars[a]['typespec']
|
||||
if vardef == 'type' and 'typename' in vars[a]:
|
||||
vardef = '%s(%s)' % (vardef, vars[a]['typename'])
|
||||
selector = {}
|
||||
lk = ''
|
||||
if 'kindselector' in vars[a]:
|
||||
selector = vars[a]['kindselector']
|
||||
lk = 'kind'
|
||||
elif 'charselector' in vars[a]:
|
||||
selector = vars[a]['charselector']
|
||||
lk = 'len'
|
||||
if '*' in selector:
|
||||
if f90mode:
|
||||
if selector['*'] in ['*', ':', '(*)']:
|
||||
vardef = '%s(len=*)' % (vardef)
|
||||
else:
|
||||
vardef = '%s(%s=%s)' % (vardef, lk, selector['*'])
|
||||
else:
|
||||
if selector['*'] in ['*', ':']:
|
||||
vardef = '%s*(%s)' % (vardef, selector['*'])
|
||||
else:
|
||||
vardef = '%s*%s' % (vardef, selector['*'])
|
||||
else:
|
||||
if 'len' in selector:
|
||||
vardef = '%s(len=%s' % (vardef, selector['len'])
|
||||
if 'kind' in selector:
|
||||
vardef = '%s,kind=%s)' % (vardef, selector['kind'])
|
||||
else:
|
||||
vardef = '%s)' % (vardef)
|
||||
elif 'kind' in selector:
|
||||
vardef = '%s(kind=%s)' % (vardef, selector['kind'])
|
||||
|
||||
vardef = '%s %s' % (vardef, fa)
|
||||
if 'dimension' in vars[a]:
|
||||
vardef = '%s(%s)' % (vardef, ','.join(vars[a]['dimension']))
|
||||
return vardef
|
||||
|
||||
def useiso_c_binding(rout):
|
||||
useisoc = False
|
||||
for key, value in rout['vars'].items():
|
||||
kind_value = value.get('kindselector', {}).get('kind')
|
||||
if kind_value in isoc_kindmap:
|
||||
return True
|
||||
return useisoc
|
||||
|
||||
def createfuncwrapper(rout, signature=0):
|
||||
assert isfunction(rout)
|
||||
|
||||
extra_args = []
|
||||
vars = rout['vars']
|
||||
for a in rout['args']:
|
||||
v = rout['vars'][a]
|
||||
for i, d in enumerate(v.get('dimension', [])):
|
||||
if d == ':':
|
||||
dn = 'f2py_%s_d%s' % (a, i)
|
||||
dv = dict(typespec='integer', intent=['hide'])
|
||||
dv['='] = 'shape(%s, %s)' % (a, i)
|
||||
extra_args.append(dn)
|
||||
vars[dn] = dv
|
||||
v['dimension'][i] = dn
|
||||
rout['args'].extend(extra_args)
|
||||
need_interface = bool(extra_args)
|
||||
|
||||
ret = ['']
|
||||
|
||||
def add(line, ret=ret):
|
||||
ret[0] = '%s\n %s' % (ret[0], line)
|
||||
name = rout['name']
|
||||
fortranname = getfortranname(rout)
|
||||
f90mode = ismoduleroutine(rout)
|
||||
newname = '%sf2pywrap' % (name)
|
||||
|
||||
if newname not in vars:
|
||||
vars[newname] = vars[name]
|
||||
args = [newname] + rout['args'][1:]
|
||||
else:
|
||||
args = [newname] + rout['args']
|
||||
|
||||
l_tmpl = var2fixfortran(vars, name, '@@@NAME@@@', f90mode)
|
||||
if l_tmpl[:13] == 'character*(*)':
|
||||
if f90mode:
|
||||
l_tmpl = 'character(len=10)' + l_tmpl[13:]
|
||||
else:
|
||||
l_tmpl = 'character*10' + l_tmpl[13:]
|
||||
charselect = vars[name]['charselector']
|
||||
if charselect.get('*', '') == '(*)':
|
||||
charselect['*'] = '10'
|
||||
|
||||
l1 = l_tmpl.replace('@@@NAME@@@', newname)
|
||||
rl = None
|
||||
|
||||
useisoc = useiso_c_binding(rout)
|
||||
sargs = ', '.join(args)
|
||||
if f90mode:
|
||||
# gh-23598 fix warning
|
||||
# Essentially, this gets called again with modules where the name of the
|
||||
# function is added to the arguments, which is not required, and removed
|
||||
sargs = sargs.replace(f"{name}, ", '')
|
||||
args = [arg for arg in args if arg != name]
|
||||
rout['args'] = args
|
||||
add('subroutine f2pywrap_%s_%s (%s)' %
|
||||
(rout['modulename'], name, sargs))
|
||||
if not signature:
|
||||
add('use %s, only : %s' % (rout['modulename'], fortranname))
|
||||
if useisoc:
|
||||
add('use iso_c_binding')
|
||||
else:
|
||||
add('subroutine f2pywrap%s (%s)' % (name, sargs))
|
||||
if useisoc:
|
||||
add('use iso_c_binding')
|
||||
if not need_interface:
|
||||
add('external %s' % (fortranname))
|
||||
rl = l_tmpl.replace('@@@NAME@@@', '') + ' ' + fortranname
|
||||
|
||||
if need_interface:
|
||||
for line in rout['saved_interface'].split('\n'):
|
||||
if line.lstrip().startswith('use ') and '__user__' not in line:
|
||||
add(line)
|
||||
|
||||
args = args[1:]
|
||||
dumped_args = []
|
||||
for a in args:
|
||||
if isexternal(vars[a]):
|
||||
add('external %s' % (a))
|
||||
dumped_args.append(a)
|
||||
for a in args:
|
||||
if a in dumped_args:
|
||||
continue
|
||||
if isscalar(vars[a]):
|
||||
add(var2fixfortran(vars, a, f90mode=f90mode))
|
||||
dumped_args.append(a)
|
||||
for a in args:
|
||||
if a in dumped_args:
|
||||
continue
|
||||
if isintent_in(vars[a]):
|
||||
add(var2fixfortran(vars, a, f90mode=f90mode))
|
||||
dumped_args.append(a)
|
||||
for a in args:
|
||||
if a in dumped_args:
|
||||
continue
|
||||
add(var2fixfortran(vars, a, f90mode=f90mode))
|
||||
|
||||
add(l1)
|
||||
if rl is not None:
|
||||
add(rl)
|
||||
|
||||
if need_interface:
|
||||
if f90mode:
|
||||
# f90 module already defines needed interface
|
||||
pass
|
||||
else:
|
||||
add('interface')
|
||||
add(rout['saved_interface'].lstrip())
|
||||
add('end interface')
|
||||
|
||||
sargs = ', '.join([a for a in args if a not in extra_args])
|
||||
|
||||
if not signature:
|
||||
if islogicalfunction(rout):
|
||||
add('%s = .not.(.not.%s(%s))' % (newname, fortranname, sargs))
|
||||
else:
|
||||
add('%s = %s(%s)' % (newname, fortranname, sargs))
|
||||
if f90mode:
|
||||
add('end subroutine f2pywrap_%s_%s' % (rout['modulename'], name))
|
||||
else:
|
||||
add('end')
|
||||
return ret[0]
|
||||
|
||||
|
||||
def createsubrwrapper(rout, signature=0):
|
||||
assert issubroutine(rout)
|
||||
|
||||
extra_args = []
|
||||
vars = rout['vars']
|
||||
for a in rout['args']:
|
||||
v = rout['vars'][a]
|
||||
for i, d in enumerate(v.get('dimension', [])):
|
||||
if d == ':':
|
||||
dn = 'f2py_%s_d%s' % (a, i)
|
||||
dv = dict(typespec='integer', intent=['hide'])
|
||||
dv['='] = 'shape(%s, %s)' % (a, i)
|
||||
extra_args.append(dn)
|
||||
vars[dn] = dv
|
||||
v['dimension'][i] = dn
|
||||
rout['args'].extend(extra_args)
|
||||
need_interface = bool(extra_args)
|
||||
|
||||
ret = ['']
|
||||
|
||||
def add(line, ret=ret):
|
||||
ret[0] = '%s\n %s' % (ret[0], line)
|
||||
name = rout['name']
|
||||
fortranname = getfortranname(rout)
|
||||
f90mode = ismoduleroutine(rout)
|
||||
|
||||
args = rout['args']
|
||||
|
||||
useisoc = useiso_c_binding(rout)
|
||||
sargs = ', '.join(args)
|
||||
if f90mode:
|
||||
add('subroutine f2pywrap_%s_%s (%s)' %
|
||||
(rout['modulename'], name, sargs))
|
||||
if useisoc:
|
||||
add('use iso_c_binding')
|
||||
if not signature:
|
||||
add('use %s, only : %s' % (rout['modulename'], fortranname))
|
||||
else:
|
||||
add('subroutine f2pywrap%s (%s)' % (name, sargs))
|
||||
if useisoc:
|
||||
add('use iso_c_binding')
|
||||
if not need_interface:
|
||||
add('external %s' % (fortranname))
|
||||
|
||||
if need_interface:
|
||||
for line in rout['saved_interface'].split('\n'):
|
||||
if line.lstrip().startswith('use ') and '__user__' not in line:
|
||||
add(line)
|
||||
|
||||
dumped_args = []
|
||||
for a in args:
|
||||
if isexternal(vars[a]):
|
||||
add('external %s' % (a))
|
||||
dumped_args.append(a)
|
||||
for a in args:
|
||||
if a in dumped_args:
|
||||
continue
|
||||
if isscalar(vars[a]):
|
||||
add(var2fixfortran(vars, a, f90mode=f90mode))
|
||||
dumped_args.append(a)
|
||||
for a in args:
|
||||
if a in dumped_args:
|
||||
continue
|
||||
add(var2fixfortran(vars, a, f90mode=f90mode))
|
||||
|
||||
if need_interface:
|
||||
if f90mode:
|
||||
# f90 module already defines needed interface
|
||||
pass
|
||||
else:
|
||||
add('interface')
|
||||
for line in rout['saved_interface'].split('\n'):
|
||||
if line.lstrip().startswith('use ') and '__user__' in line:
|
||||
continue
|
||||
add(line)
|
||||
add('end interface')
|
||||
|
||||
sargs = ', '.join([a for a in args if a not in extra_args])
|
||||
|
||||
if not signature:
|
||||
add('call %s(%s)' % (fortranname, sargs))
|
||||
if f90mode:
|
||||
add('end subroutine f2pywrap_%s_%s' % (rout['modulename'], name))
|
||||
else:
|
||||
add('end')
|
||||
return ret[0]
|
||||
|
||||
|
||||
def assubr(rout):
|
||||
if isfunction_wrap(rout):
|
||||
fortranname = getfortranname(rout)
|
||||
name = rout['name']
|
||||
outmess('\t\tCreating wrapper for Fortran function "%s"("%s")...\n' % (
|
||||
name, fortranname))
|
||||
rout = copy.copy(rout)
|
||||
fname = name
|
||||
rname = fname
|
||||
if 'result' in rout:
|
||||
rname = rout['result']
|
||||
rout['vars'][fname] = rout['vars'][rname]
|
||||
fvar = rout['vars'][fname]
|
||||
if not isintent_out(fvar):
|
||||
if 'intent' not in fvar:
|
||||
fvar['intent'] = []
|
||||
fvar['intent'].append('out')
|
||||
flag = 1
|
||||
for i in fvar['intent']:
|
||||
if i.startswith('out='):
|
||||
flag = 0
|
||||
break
|
||||
if flag:
|
||||
fvar['intent'].append('out=%s' % (rname))
|
||||
rout['args'][:] = [fname] + rout['args']
|
||||
return rout, createfuncwrapper(rout)
|
||||
if issubroutine_wrap(rout):
|
||||
fortranname = getfortranname(rout)
|
||||
name = rout['name']
|
||||
outmess('\t\tCreating wrapper for Fortran subroutine "%s"("%s")...\n'
|
||||
% (name, fortranname))
|
||||
rout = copy.copy(rout)
|
||||
return rout, createsubrwrapper(rout)
|
||||
return rout, ''
|
1573
lib/python3.13/site-packages/numpy/f2py/rules.py
Executable file
1573
lib/python3.13/site-packages/numpy/f2py/rules.py
Executable file
File diff suppressed because it is too large
Load Diff
3
lib/python3.13/site-packages/numpy/f2py/setup.cfg
Normal file
3
lib/python3.13/site-packages/numpy/f2py/setup.cfg
Normal file
@ -0,0 +1,3 @@
|
||||
[bdist_rpm]
|
||||
doc_files = docs/
|
||||
tests/
|
1423
lib/python3.13/site-packages/numpy/f2py/src/fortranobject.c
Normal file
1423
lib/python3.13/site-packages/numpy/f2py/src/fortranobject.c
Normal file
File diff suppressed because it is too large
Load Diff
173
lib/python3.13/site-packages/numpy/f2py/src/fortranobject.h
Normal file
173
lib/python3.13/site-packages/numpy/f2py/src/fortranobject.h
Normal file
@ -0,0 +1,173 @@
|
||||
#ifndef Py_FORTRANOBJECT_H
|
||||
#define Py_FORTRANOBJECT_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#ifndef NPY_NO_DEPRECATED_API
|
||||
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
|
||||
#endif
|
||||
#ifdef FORTRANOBJECT_C
|
||||
#define NO_IMPORT_ARRAY
|
||||
#endif
|
||||
#define PY_ARRAY_UNIQUE_SYMBOL _npy_f2py_ARRAY_API
|
||||
#include "numpy/arrayobject.h"
|
||||
#include "numpy/npy_3kcompat.h"
|
||||
|
||||
#ifdef F2PY_REPORT_ATEXIT
|
||||
#include <sys/timeb.h>
|
||||
// clang-format off
|
||||
extern void f2py_start_clock(void);
|
||||
extern void f2py_stop_clock(void);
|
||||
extern void f2py_start_call_clock(void);
|
||||
extern void f2py_stop_call_clock(void);
|
||||
extern void f2py_cb_start_clock(void);
|
||||
extern void f2py_cb_stop_clock(void);
|
||||
extern void f2py_cb_start_call_clock(void);
|
||||
extern void f2py_cb_stop_call_clock(void);
|
||||
extern void f2py_report_on_exit(int, void *);
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
#ifdef DMALLOC
|
||||
#include "dmalloc.h"
|
||||
#endif
|
||||
|
||||
/* Fortran object interface */
|
||||
|
||||
/*
|
||||
123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
|
||||
|
||||
PyFortranObject represents various Fortran objects:
|
||||
Fortran (module) routines, COMMON blocks, module data.
|
||||
|
||||
Author: Pearu Peterson <pearu@cens.ioc.ee>
|
||||
*/
|
||||
|
||||
#define F2PY_MAX_DIMS 40
|
||||
#define F2PY_MESSAGE_BUFFER_SIZE 300 // Increase on "stack smashing detected"
|
||||
|
||||
typedef void (*f2py_set_data_func)(char *, npy_intp *);
|
||||
typedef void (*f2py_void_func)(void);
|
||||
typedef void (*f2py_init_func)(int *, npy_intp *, f2py_set_data_func, int *);
|
||||
|
||||
/*typedef void* (*f2py_c_func)(void*,...);*/
|
||||
|
||||
typedef void *(*f2pycfunc)(void);
|
||||
|
||||
typedef struct {
|
||||
char *name; /* attribute (array||routine) name */
|
||||
int rank; /* array rank, 0 for scalar, max is F2PY_MAX_DIMS,
|
||||
|| rank=-1 for Fortran routine */
|
||||
struct {
|
||||
npy_intp d[F2PY_MAX_DIMS];
|
||||
} dims; /* dimensions of the array, || not used */
|
||||
int type; /* PyArray_<type> || not used */
|
||||
int elsize; /* Element size || not used */
|
||||
char *data; /* pointer to array || Fortran routine */
|
||||
f2py_init_func func; /* initialization function for
|
||||
allocatable arrays:
|
||||
func(&rank,dims,set_ptr_func,name,len(name))
|
||||
|| C/API wrapper for Fortran routine */
|
||||
char *doc; /* documentation string; only recommended
|
||||
for routines. */
|
||||
} FortranDataDef;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
int len; /* Number of attributes */
|
||||
FortranDataDef *defs; /* An array of FortranDataDef's */
|
||||
PyObject *dict; /* Fortran object attribute dictionary */
|
||||
} PyFortranObject;
|
||||
|
||||
#define PyFortran_Check(op) (Py_TYPE(op) == &PyFortran_Type)
|
||||
#define PyFortran_Check1(op) (0 == strcmp(Py_TYPE(op)->tp_name, "fortran"))
|
||||
|
||||
extern PyTypeObject PyFortran_Type;
|
||||
extern int
|
||||
F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj);
|
||||
extern PyObject *
|
||||
PyFortranObject_New(FortranDataDef *defs, f2py_void_func init);
|
||||
extern PyObject *
|
||||
PyFortranObject_NewAsAttr(FortranDataDef *defs);
|
||||
|
||||
PyObject *
|
||||
F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *));
|
||||
void *
|
||||
F2PyCapsule_AsVoidPtr(PyObject *obj);
|
||||
int
|
||||
F2PyCapsule_Check(PyObject *ptr);
|
||||
|
||||
extern void *
|
||||
F2PySwapThreadLocalCallbackPtr(char *key, void *ptr);
|
||||
extern void *
|
||||
F2PyGetThreadLocalCallbackPtr(char *key);
|
||||
|
||||
#define ISCONTIGUOUS(m) (PyArray_FLAGS(m) & NPY_ARRAY_C_CONTIGUOUS)
|
||||
#define F2PY_INTENT_IN 1
|
||||
#define F2PY_INTENT_INOUT 2
|
||||
#define F2PY_INTENT_OUT 4
|
||||
#define F2PY_INTENT_HIDE 8
|
||||
#define F2PY_INTENT_CACHE 16
|
||||
#define F2PY_INTENT_COPY 32
|
||||
#define F2PY_INTENT_C 64
|
||||
#define F2PY_OPTIONAL 128
|
||||
#define F2PY_INTENT_INPLACE 256
|
||||
#define F2PY_INTENT_ALIGNED4 512
|
||||
#define F2PY_INTENT_ALIGNED8 1024
|
||||
#define F2PY_INTENT_ALIGNED16 2048
|
||||
|
||||
#define ARRAY_ISALIGNED(ARR, SIZE) ((size_t)(PyArray_DATA(ARR)) % (SIZE) == 0)
|
||||
#define F2PY_ALIGN4(intent) (intent & F2PY_INTENT_ALIGNED4)
|
||||
#define F2PY_ALIGN8(intent) (intent & F2PY_INTENT_ALIGNED8)
|
||||
#define F2PY_ALIGN16(intent) (intent & F2PY_INTENT_ALIGNED16)
|
||||
|
||||
#define F2PY_GET_ALIGNMENT(intent) \
|
||||
(F2PY_ALIGN4(intent) \
|
||||
? 4 \
|
||||
: (F2PY_ALIGN8(intent) ? 8 : (F2PY_ALIGN16(intent) ? 16 : 1)))
|
||||
#define F2PY_CHECK_ALIGNMENT(arr, intent) \
|
||||
ARRAY_ISALIGNED(arr, F2PY_GET_ALIGNMENT(intent))
|
||||
#define F2PY_ARRAY_IS_CHARACTER_COMPATIBLE(arr) ((PyArray_DESCR(arr)->type_num == NPY_STRING && PyArray_ITEMSIZE(arr) >= 1) \
|
||||
|| PyArray_DESCR(arr)->type_num == NPY_UINT8)
|
||||
#define F2PY_IS_UNICODE_ARRAY(arr) (PyArray_DESCR(arr)->type_num == NPY_UNICODE)
|
||||
|
||||
extern PyArrayObject *
|
||||
ndarray_from_pyobj(const int type_num, const int elsize_, npy_intp *dims,
|
||||
const int rank, const int intent, PyObject *obj,
|
||||
const char *errmess);
|
||||
|
||||
extern PyArrayObject *
|
||||
array_from_pyobj(const int type_num, npy_intp *dims, const int rank,
|
||||
const int intent, PyObject *obj);
|
||||
extern int
|
||||
copy_ND_array(const PyArrayObject *in, PyArrayObject *out);
|
||||
|
||||
#ifdef DEBUG_COPY_ND_ARRAY
|
||||
extern void
|
||||
dump_attrs(const PyArrayObject *arr);
|
||||
#endif
|
||||
|
||||
extern int f2py_describe(PyObject *obj, char *buf);
|
||||
|
||||
/* Utility CPP macros and functions that can be used in signature file
|
||||
expressions. See signature-file.rst for documentation.
|
||||
*/
|
||||
|
||||
#define f2py_itemsize(var) (PyArray_ITEMSIZE(capi_ ## var ## _as_array))
|
||||
#define f2py_size(var, ...) f2py_size_impl((PyArrayObject *)(capi_ ## var ## _as_array), ## __VA_ARGS__, -1)
|
||||
#define f2py_rank(var) var ## _Rank
|
||||
#define f2py_shape(var,dim) var ## _Dims[dim]
|
||||
#define f2py_len(var) f2py_shape(var,0)
|
||||
#define f2py_fshape(var,dim) f2py_shape(var,rank(var)-dim-1)
|
||||
#define f2py_flen(var) f2py_fshape(var,0)
|
||||
#define f2py_slen(var) capi_ ## var ## _len
|
||||
|
||||
extern npy_intp f2py_size_impl(PyArrayObject* var, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_FORTRANOBJECT_H */
|
1517
lib/python3.13/site-packages/numpy/f2py/symbolic.py
Normal file
1517
lib/python3.13/site-packages/numpy/f2py/symbolic.py
Normal file
File diff suppressed because it is too large
Load Diff
15
lib/python3.13/site-packages/numpy/f2py/tests/__init__.py
Normal file
15
lib/python3.13/site-packages/numpy/f2py/tests/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
from numpy.testing import IS_WASM, IS_EDITABLE
|
||||
import pytest
|
||||
|
||||
if IS_WASM:
|
||||
pytest.skip(
|
||||
"WASM/Pyodide does not use or support Fortran",
|
||||
allow_module_level=True
|
||||
)
|
||||
|
||||
|
||||
if IS_EDITABLE:
|
||||
pytest.skip(
|
||||
"Editable install doesn't support tests with a compile step",
|
||||
allow_module_level=True
|
||||
)
|
@ -0,0 +1,34 @@
|
||||
module ops_module
|
||||
|
||||
abstract interface
|
||||
subroutine op(x, y, z)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: z
|
||||
end subroutine
|
||||
end interface
|
||||
|
||||
contains
|
||||
|
||||
subroutine foo(x, y, r1, r2)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: r1, r2
|
||||
procedure (op) add1, add2
|
||||
procedure (op), pointer::p
|
||||
p=>add1
|
||||
call p(x, y, r1)
|
||||
p=>add2
|
||||
call p(x, y, r2)
|
||||
end subroutine
|
||||
end module
|
||||
|
||||
subroutine add1(x, y, z)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: z
|
||||
z = x + y
|
||||
end subroutine
|
||||
|
||||
subroutine add2(x, y, z)
|
||||
integer, intent(in) :: x, y
|
||||
integer, intent(out) :: z
|
||||
z = x + 2 * y
|
||||
end subroutine
|
@ -0,0 +1,6 @@
|
||||
module test
|
||||
abstract interface
|
||||
subroutine foo()
|
||||
end subroutine
|
||||
end interface
|
||||
end module test
|
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* This file was auto-generated with f2py (version:2_1330) and hand edited by
|
||||
* Pearu for testing purposes. Do not edit this file unless you know what you
|
||||
* are doing!!!
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************** See f2py2e/cfuncs.py: includes ***********************/
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#include "fortranobject.h"
|
||||
#include <math.h>
|
||||
|
||||
static PyObject *wrap_error;
|
||||
static PyObject *wrap_module;
|
||||
|
||||
/************************************ call ************************************/
|
||||
static char doc_f2py_rout_wrap_call[] = "\
|
||||
Function signature:\n\
|
||||
arr = call(type_num,dims,intent,obj)\n\
|
||||
Required arguments:\n"
|
||||
" type_num : input int\n"
|
||||
" dims : input int-sequence\n"
|
||||
" intent : input int\n"
|
||||
" obj : input python object\n"
|
||||
"Return objects:\n"
|
||||
" arr : array";
|
||||
static PyObject *f2py_rout_wrap_call(PyObject *capi_self,
|
||||
PyObject *capi_args) {
|
||||
PyObject * volatile capi_buildvalue = NULL;
|
||||
int type_num = 0;
|
||||
int elsize = 0;
|
||||
npy_intp *dims = NULL;
|
||||
PyObject *dims_capi = Py_None;
|
||||
int rank = 0;
|
||||
int intent = 0;
|
||||
PyArrayObject *capi_arr_tmp = NULL;
|
||||
PyObject *arr_capi = Py_None;
|
||||
int i;
|
||||
|
||||
if (!PyArg_ParseTuple(capi_args,"iiOiO|:wrap.call",\
|
||||
&type_num,&elsize,&dims_capi,&intent,&arr_capi))
|
||||
return NULL;
|
||||
rank = PySequence_Length(dims_capi);
|
||||
dims = malloc(rank*sizeof(npy_intp));
|
||||
for (i=0;i<rank;++i) {
|
||||
PyObject *tmp;
|
||||
tmp = PySequence_GetItem(dims_capi, i);
|
||||
if (tmp == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
dims[i] = (npy_intp)PyLong_AsLong(tmp);
|
||||
Py_DECREF(tmp);
|
||||
if (dims[i] == -1 && PyErr_Occurred()) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
capi_arr_tmp = ndarray_from_pyobj(type_num,elsize,dims,rank,intent|F2PY_INTENT_OUT,arr_capi,"wrap.call failed");
|
||||
if (capi_arr_tmp == NULL) {
|
||||
free(dims);
|
||||
return NULL;
|
||||
}
|
||||
capi_buildvalue = Py_BuildValue("N",capi_arr_tmp);
|
||||
free(dims);
|
||||
return capi_buildvalue;
|
||||
|
||||
fail:
|
||||
free(dims);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char doc_f2py_rout_wrap_attrs[] = "\
|
||||
Function signature:\n\
|
||||
arr = array_attrs(arr)\n\
|
||||
Required arguments:\n"
|
||||
" arr : input array object\n"
|
||||
"Return objects:\n"
|
||||
" data : data address in hex\n"
|
||||
" nd : int\n"
|
||||
" dimensions : tuple\n"
|
||||
" strides : tuple\n"
|
||||
" base : python object\n"
|
||||
" (kind,type,type_num,elsize,alignment) : 4-tuple\n"
|
||||
" flags : int\n"
|
||||
" itemsize : int\n"
|
||||
;
|
||||
static PyObject *f2py_rout_wrap_attrs(PyObject *capi_self,
|
||||
PyObject *capi_args) {
|
||||
PyObject *arr_capi = Py_None;
|
||||
PyArrayObject *arr = NULL;
|
||||
PyObject *dimensions = NULL;
|
||||
PyObject *strides = NULL;
|
||||
char s[100];
|
||||
int i;
|
||||
memset(s,0,100);
|
||||
if (!PyArg_ParseTuple(capi_args,"O!|:wrap.attrs",
|
||||
&PyArray_Type,&arr_capi))
|
||||
return NULL;
|
||||
arr = (PyArrayObject *)arr_capi;
|
||||
sprintf(s,"%p",PyArray_DATA(arr));
|
||||
dimensions = PyTuple_New(PyArray_NDIM(arr));
|
||||
strides = PyTuple_New(PyArray_NDIM(arr));
|
||||
for (i=0;i<PyArray_NDIM(arr);++i) {
|
||||
PyTuple_SetItem(dimensions,i,PyLong_FromLong(PyArray_DIM(arr,i)));
|
||||
PyTuple_SetItem(strides,i,PyLong_FromLong(PyArray_STRIDE(arr,i)));
|
||||
}
|
||||
return Py_BuildValue("siNNO(cciii)ii",s,PyArray_NDIM(arr),
|
||||
dimensions,strides,
|
||||
(PyArray_BASE(arr)==NULL?Py_None:PyArray_BASE(arr)),
|
||||
PyArray_DESCR(arr)->kind,
|
||||
PyArray_DESCR(arr)->type,
|
||||
PyArray_TYPE(arr),
|
||||
PyArray_ITEMSIZE(arr),
|
||||
PyDataType_ALIGNMENT(PyArray_DESCR(arr)),
|
||||
PyArray_FLAGS(arr),
|
||||
PyArray_ITEMSIZE(arr));
|
||||
}
|
||||
|
||||
static PyMethodDef f2py_module_methods[] = {
|
||||
|
||||
{"call",f2py_rout_wrap_call,METH_VARARGS,doc_f2py_rout_wrap_call},
|
||||
{"array_attrs",f2py_rout_wrap_attrs,METH_VARARGS,doc_f2py_rout_wrap_attrs},
|
||||
{NULL,NULL}
|
||||
};
|
||||
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"test_array_from_pyobj_ext",
|
||||
NULL,
|
||||
-1,
|
||||
f2py_module_methods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC PyInit_test_array_from_pyobj_ext(void) {
|
||||
PyObject *m,*d, *s;
|
||||
m = wrap_module = PyModule_Create(&moduledef);
|
||||
Py_SET_TYPE(&PyFortran_Type, &PyType_Type);
|
||||
import_array();
|
||||
if (PyErr_Occurred())
|
||||
Py_FatalError("can't initialize module wrap (failed to import numpy)");
|
||||
d = PyModule_GetDict(m);
|
||||
s = PyUnicode_FromString("This module 'wrap' is auto-generated with f2py (version:2_1330).\nFunctions:\n"
|
||||
" arr = call(type_num,dims,intent,obj)\n"
|
||||
".");
|
||||
PyDict_SetItemString(d, "__doc__", s);
|
||||
wrap_error = PyErr_NewException ("wrap.error", NULL, NULL);
|
||||
Py_DECREF(s);
|
||||
|
||||
#define ADDCONST(NAME, CONST) \
|
||||
s = PyLong_FromLong(CONST); \
|
||||
PyDict_SetItemString(d, NAME, s); \
|
||||
Py_DECREF(s)
|
||||
|
||||
ADDCONST("F2PY_INTENT_IN", F2PY_INTENT_IN);
|
||||
ADDCONST("F2PY_INTENT_INOUT", F2PY_INTENT_INOUT);
|
||||
ADDCONST("F2PY_INTENT_OUT", F2PY_INTENT_OUT);
|
||||
ADDCONST("F2PY_INTENT_HIDE", F2PY_INTENT_HIDE);
|
||||
ADDCONST("F2PY_INTENT_CACHE", F2PY_INTENT_CACHE);
|
||||
ADDCONST("F2PY_INTENT_COPY", F2PY_INTENT_COPY);
|
||||
ADDCONST("F2PY_INTENT_C", F2PY_INTENT_C);
|
||||
ADDCONST("F2PY_OPTIONAL", F2PY_OPTIONAL);
|
||||
ADDCONST("F2PY_INTENT_INPLACE", F2PY_INTENT_INPLACE);
|
||||
ADDCONST("NPY_BOOL", NPY_BOOL);
|
||||
ADDCONST("NPY_BYTE", NPY_BYTE);
|
||||
ADDCONST("NPY_UBYTE", NPY_UBYTE);
|
||||
ADDCONST("NPY_SHORT", NPY_SHORT);
|
||||
ADDCONST("NPY_USHORT", NPY_USHORT);
|
||||
ADDCONST("NPY_INT", NPY_INT);
|
||||
ADDCONST("NPY_UINT", NPY_UINT);
|
||||
ADDCONST("NPY_INTP", NPY_INTP);
|
||||
ADDCONST("NPY_UINTP", NPY_UINTP);
|
||||
ADDCONST("NPY_LONG", NPY_LONG);
|
||||
ADDCONST("NPY_ULONG", NPY_ULONG);
|
||||
ADDCONST("NPY_LONGLONG", NPY_LONGLONG);
|
||||
ADDCONST("NPY_ULONGLONG", NPY_ULONGLONG);
|
||||
ADDCONST("NPY_FLOAT", NPY_FLOAT);
|
||||
ADDCONST("NPY_DOUBLE", NPY_DOUBLE);
|
||||
ADDCONST("NPY_LONGDOUBLE", NPY_LONGDOUBLE);
|
||||
ADDCONST("NPY_CFLOAT", NPY_CFLOAT);
|
||||
ADDCONST("NPY_CDOUBLE", NPY_CDOUBLE);
|
||||
ADDCONST("NPY_CLONGDOUBLE", NPY_CLONGDOUBLE);
|
||||
ADDCONST("NPY_OBJECT", NPY_OBJECT);
|
||||
ADDCONST("NPY_STRING", NPY_STRING);
|
||||
ADDCONST("NPY_UNICODE", NPY_UNICODE);
|
||||
ADDCONST("NPY_VOID", NPY_VOID);
|
||||
ADDCONST("NPY_NTYPES_LEGACY", NPY_NTYPES_LEGACY);
|
||||
ADDCONST("NPY_NOTYPE", NPY_NOTYPE);
|
||||
ADDCONST("NPY_USERDEF", NPY_USERDEF);
|
||||
|
||||
ADDCONST("CONTIGUOUS", NPY_ARRAY_C_CONTIGUOUS);
|
||||
ADDCONST("FORTRAN", NPY_ARRAY_F_CONTIGUOUS);
|
||||
ADDCONST("OWNDATA", NPY_ARRAY_OWNDATA);
|
||||
ADDCONST("FORCECAST", NPY_ARRAY_FORCECAST);
|
||||
ADDCONST("ENSURECOPY", NPY_ARRAY_ENSURECOPY);
|
||||
ADDCONST("ENSUREARRAY", NPY_ARRAY_ENSUREARRAY);
|
||||
ADDCONST("ALIGNED", NPY_ARRAY_ALIGNED);
|
||||
ADDCONST("WRITEABLE", NPY_ARRAY_WRITEABLE);
|
||||
ADDCONST("WRITEBACKIFCOPY", NPY_ARRAY_WRITEBACKIFCOPY);
|
||||
|
||||
ADDCONST("BEHAVED", NPY_ARRAY_BEHAVED);
|
||||
ADDCONST("BEHAVED_NS", NPY_ARRAY_BEHAVED_NS);
|
||||
ADDCONST("CARRAY", NPY_ARRAY_CARRAY);
|
||||
ADDCONST("FARRAY", NPY_ARRAY_FARRAY);
|
||||
ADDCONST("CARRAY_RO", NPY_ARRAY_CARRAY_RO);
|
||||
ADDCONST("FARRAY_RO", NPY_ARRAY_FARRAY_RO);
|
||||
ADDCONST("DEFAULT", NPY_ARRAY_DEFAULT);
|
||||
ADDCONST("UPDATE_ALL", NPY_ARRAY_UPDATE_ALL);
|
||||
|
||||
#undef ADDCONST
|
||||
|
||||
if (PyErr_Occurred())
|
||||
Py_FatalError("can't initialize module wrap");
|
||||
|
||||
#ifdef F2PY_REPORT_ATEXIT
|
||||
on_exit(f2py_report_on_exit,(void*)"array_from_pyobj.wrap.call");
|
||||
#endif
|
||||
|
||||
#if Py_GIL_DISABLED
|
||||
// signal whether this module supports running with the GIL disabled
|
||||
PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
|
||||
#endif
|
||||
|
||||
return m;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1 @@
|
||||
dict(real=dict(rk="double"))
|
@ -0,0 +1,34 @@
|
||||
|
||||
subroutine sum(x, res)
|
||||
implicit none
|
||||
real, intent(in) :: x(:)
|
||||
real, intent(out) :: res
|
||||
|
||||
integer :: i
|
||||
|
||||
!print *, "sum: size(x) = ", size(x)
|
||||
|
||||
res = 0.0
|
||||
|
||||
do i = 1, size(x)
|
||||
res = res + x(i)
|
||||
enddo
|
||||
|
||||
end subroutine sum
|
||||
|
||||
function fsum(x) result (res)
|
||||
implicit none
|
||||
real, intent(in) :: x(:)
|
||||
real :: res
|
||||
|
||||
integer :: i
|
||||
|
||||
!print *, "fsum: size(x) = ", size(x)
|
||||
|
||||
res = 0.0
|
||||
|
||||
do i = 1, size(x)
|
||||
res = res + x(i)
|
||||
enddo
|
||||
|
||||
end function fsum
|
@ -0,0 +1,41 @@
|
||||
|
||||
module mod
|
||||
|
||||
contains
|
||||
|
||||
subroutine sum(x, res)
|
||||
implicit none
|
||||
real, intent(in) :: x(:)
|
||||
real, intent(out) :: res
|
||||
|
||||
integer :: i
|
||||
|
||||
!print *, "sum: size(x) = ", size(x)
|
||||
|
||||
res = 0.0
|
||||
|
||||
do i = 1, size(x)
|
||||
res = res + x(i)
|
||||
enddo
|
||||
|
||||
end subroutine sum
|
||||
|
||||
function fsum(x) result (res)
|
||||
implicit none
|
||||
real, intent(in) :: x(:)
|
||||
real :: res
|
||||
|
||||
integer :: i
|
||||
|
||||
!print *, "fsum: size(x) = ", size(x)
|
||||
|
||||
res = 0.0
|
||||
|
||||
do i = 1, size(x)
|
||||
res = res + x(i)
|
||||
enddo
|
||||
|
||||
end function fsum
|
||||
|
||||
|
||||
end module mod
|
@ -0,0 +1,19 @@
|
||||
subroutine sum_with_use(x, res)
|
||||
use precision
|
||||
|
||||
implicit none
|
||||
|
||||
real(kind=rk), intent(in) :: x(:)
|
||||
real(kind=rk), intent(out) :: res
|
||||
|
||||
integer :: i
|
||||
|
||||
!print *, "size(x) = ", size(x)
|
||||
|
||||
res = 0.0
|
||||
|
||||
do i = 1, size(x)
|
||||
res = res + x(i)
|
||||
enddo
|
||||
|
||||
end subroutine
|
@ -0,0 +1,4 @@
|
||||
module precision
|
||||
integer, parameter :: rk = selected_real_kind(8)
|
||||
integer, parameter :: ik = selected_real_kind(4)
|
||||
end module
|
@ -0,0 +1,6 @@
|
||||
SUBROUTINE FOO()
|
||||
INTEGER BAR(2, 3)
|
||||
|
||||
COMMON /BLOCK/ BAR
|
||||
RETURN
|
||||
END
|
@ -0,0 +1,62 @@
|
||||
subroutine t(fun,a)
|
||||
integer a
|
||||
cf2py intent(out) a
|
||||
external fun
|
||||
call fun(a)
|
||||
end
|
||||
|
||||
subroutine func(a)
|
||||
cf2py intent(in,out) a
|
||||
integer a
|
||||
a = a + 11
|
||||
end
|
||||
|
||||
subroutine func0(a)
|
||||
cf2py intent(out) a
|
||||
integer a
|
||||
a = 11
|
||||
end
|
||||
|
||||
subroutine t2(a)
|
||||
cf2py intent(callback) fun
|
||||
integer a
|
||||
cf2py intent(out) a
|
||||
external fun
|
||||
call fun(a)
|
||||
end
|
||||
|
||||
subroutine string_callback(callback, a)
|
||||
external callback
|
||||
double precision callback
|
||||
double precision a
|
||||
character*1 r
|
||||
cf2py intent(out) a
|
||||
r = 'r'
|
||||
a = callback(r)
|
||||
end
|
||||
|
||||
subroutine string_callback_array(callback, cu, lencu, a)
|
||||
external callback
|
||||
integer callback
|
||||
integer lencu
|
||||
character*8 cu(lencu)
|
||||
integer a
|
||||
cf2py intent(out) a
|
||||
|
||||
a = callback(cu, lencu)
|
||||
end
|
||||
|
||||
subroutine hidden_callback(a, r)
|
||||
external global_f
|
||||
cf2py intent(callback, hide) global_f
|
||||
integer a, r, global_f
|
||||
cf2py intent(out) r
|
||||
r = global_f(a)
|
||||
end
|
||||
|
||||
subroutine hidden_callback2(a, r)
|
||||
external global_f
|
||||
integer a, r, global_f
|
||||
cf2py intent(out) r
|
||||
r = global_f(a)
|
||||
end
|
@ -0,0 +1,7 @@
|
||||
function gh17797(f, y) result(r)
|
||||
external f
|
||||
integer(8) :: r, f
|
||||
integer(8), dimension(:) :: y
|
||||
r = f(0)
|
||||
r = r + sum(y)
|
||||
end function gh17797
|
@ -0,0 +1,17 @@
|
||||
! When gh18335_workaround is defined as an extension,
|
||||
! the issue cannot be reproduced.
|
||||
!subroutine gh18335_workaround(f, y)
|
||||
! implicit none
|
||||
! external f
|
||||
! integer(kind=1) :: y(1)
|
||||
! call f(y)
|
||||
!end subroutine gh18335_workaround
|
||||
|
||||
function gh18335(f) result (r)
|
||||
implicit none
|
||||
external f
|
||||
integer(kind=1) :: y(1), r
|
||||
y(1) = 123
|
||||
call f(y)
|
||||
r = y(1)
|
||||
end function gh18335
|
@ -0,0 +1,10 @@
|
||||
SUBROUTINE FOO(FUN,R)
|
||||
EXTERNAL FUN
|
||||
INTEGER I
|
||||
REAL*8 R, FUN
|
||||
Cf2py intent(out) r
|
||||
R = 0D0
|
||||
DO I=-5,5
|
||||
R = R + FUN(I)
|
||||
ENDDO
|
||||
END
|
@ -0,0 +1,18 @@
|
||||
python module __user__routines
|
||||
interface
|
||||
function fun(i) result (r)
|
||||
integer :: i
|
||||
real*8 :: r
|
||||
end function fun
|
||||
end interface
|
||||
end python module __user__routines
|
||||
|
||||
python module callback2
|
||||
interface
|
||||
subroutine foo(f,r)
|
||||
use __user__routines, f=>fun
|
||||
external f
|
||||
real*8 intent(out) :: r
|
||||
end subroutine foo
|
||||
end interface
|
||||
end python module callback2
|
@ -0,0 +1,6 @@
|
||||
python module test_22819
|
||||
interface
|
||||
subroutine hello()
|
||||
end subroutine hello
|
||||
end interface
|
||||
end python module test_22819
|
@ -0,0 +1,3 @@
|
||||
SUBROUTINE HI
|
||||
PRINT*, "HELLO WORLD"
|
||||
END SUBROUTINE
|
@ -0,0 +1,3 @@
|
||||
function hi()
|
||||
print*, "Hello World"
|
||||
end function
|
@ -0,0 +1,11 @@
|
||||
SUBROUTINE INITCB
|
||||
DOUBLE PRECISION LONG
|
||||
CHARACTER STRING
|
||||
INTEGER OK
|
||||
|
||||
COMMON /BLOCK/ LONG, STRING, OK
|
||||
LONG = 1.0
|
||||
STRING = '2'
|
||||
OK = 3
|
||||
RETURN
|
||||
END
|
@ -0,0 +1,10 @@
|
||||
module typedefmod
|
||||
use iso_fortran_env, only: real32
|
||||
end module typedefmod
|
||||
|
||||
module data
|
||||
use typedefmod, only: real32
|
||||
implicit none
|
||||
real(kind=real32) :: x
|
||||
common/test/x
|
||||
end module data
|
@ -0,0 +1,13 @@
|
||||
module foo
|
||||
public
|
||||
type, private, bind(c) :: a
|
||||
integer :: i
|
||||
end type a
|
||||
type, bind(c) :: b_
|
||||
integer :: j
|
||||
end type b_
|
||||
public :: b_
|
||||
type :: c
|
||||
integer :: k
|
||||
end type c
|
||||
end module foo
|
@ -0,0 +1,8 @@
|
||||
BLOCK DATA PARAM_INI
|
||||
COMMON /MYCOM/ MYDATA
|
||||
DATA MYDATA /0/
|
||||
END
|
||||
SUBROUTINE SUB1
|
||||
COMMON /MYCOM/ MYDATA
|
||||
MYDATA = MYDATA + 1
|
||||
END
|
@ -0,0 +1,5 @@
|
||||
BLOCK DATA MYBLK
|
||||
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
|
||||
COMMON /MYCOM/ IVAR1, IVAR2, IVAR3, IVAR4, EVAR5
|
||||
DATA IVAR1, IVAR2, IVAR3, IVAR4, EVAR5 /2*3,2*2,0.0D0/
|
||||
END
|
@ -0,0 +1,20 @@
|
||||
! gh-23276
|
||||
module cmplxdat
|
||||
implicit none
|
||||
integer :: i, j
|
||||
real :: x, y
|
||||
real, dimension(2) :: z
|
||||
real(kind=8) :: pi
|
||||
complex(kind=8), target :: medium_ref_index
|
||||
complex(kind=8), target :: ref_index_one, ref_index_two
|
||||
complex(kind=8), dimension(2) :: my_array
|
||||
real(kind=8), dimension(3) :: my_real_array = (/1.0d0, 2.0d0, 3.0d0/)
|
||||
|
||||
data i, j / 2, 3 /
|
||||
data x, y / 1.5, 2.0 /
|
||||
data z / 3.5, 7.0 /
|
||||
data medium_ref_index / (1.d0, 0.d0) /
|
||||
data ref_index_one, ref_index_two / (13.0d0, 21.0d0), (-30.0d0, 43.0d0) /
|
||||
data my_array / (1.0d0, 2.0d0), (-3.0d0, 4.0d0) /
|
||||
data pi / 3.1415926535897932384626433832795028841971693993751058209749445923078164062d0 /
|
||||
end module cmplxdat
|
@ -0,0 +1,8 @@
|
||||
BLOCK DATA PARAM_INI
|
||||
COMMON /MYCOM/ MYTAB
|
||||
INTEGER MYTAB(3)
|
||||
DATA MYTAB/
|
||||
* 0, ! 1 and more commenty stuff
|
||||
* 4, ! 2
|
||||
* 0 /
|
||||
END
|
@ -0,0 +1,6 @@
|
||||
module foo
|
||||
type bar
|
||||
character(len = 4) :: text
|
||||
end type bar
|
||||
type(bar), parameter :: abar = bar('abar')
|
||||
end module foo
|
@ -0,0 +1,16 @@
|
||||
subroutine subb(k)
|
||||
real(8), intent(inout) :: k(:)
|
||||
k=k+1
|
||||
endsubroutine
|
||||
|
||||
subroutine subc(w,k)
|
||||
real(8), intent(in) :: w(:)
|
||||
real(8), intent(out) :: k(size(w))
|
||||
k=w+1
|
||||
endsubroutine
|
||||
|
||||
function t0(value)
|
||||
character value
|
||||
character t0
|
||||
t0 = value
|
||||
endfunction
|
@ -0,0 +1,12 @@
|
||||
integer(8) function external_as_statement(fcn)
|
||||
implicit none
|
||||
external fcn
|
||||
integer(8) :: fcn
|
||||
external_as_statement = fcn(0)
|
||||
end
|
||||
|
||||
integer(8) function external_as_attribute(fcn)
|
||||
implicit none
|
||||
integer(8), external :: fcn
|
||||
external_as_attribute = fcn(0)
|
||||
end
|
@ -0,0 +1,7 @@
|
||||
python module iri16py ! in
|
||||
interface ! in :iri16py
|
||||
block data ! in :iri16py:iridreg_modified.for
|
||||
COMMON /fircom/ eden,tabhe,tabla,tabmo,tabza,tabfl
|
||||
end block data
|
||||
end interface
|
||||
end python module iri16py
|
@ -0,0 +1,5 @@
|
||||
SUBROUTINE EXAMPLE( )
|
||||
IF( .TRUE. ) THEN
|
||||
CALL DO_SOMETHING()
|
||||
END IF ! ** .TRUE. **
|
||||
END
|
@ -0,0 +1,4 @@
|
||||
integer function intproduct(a, b) result(res)
|
||||
integer, intent(in) :: a, b
|
||||
res = a*b
|
||||
end function
|
@ -0,0 +1,11 @@
|
||||
module test_bug
|
||||
implicit none
|
||||
private
|
||||
public :: intproduct
|
||||
|
||||
contains
|
||||
integer function intproduct(a, b) result(res)
|
||||
integer, intent(in) :: a, b
|
||||
res = a*b
|
||||
end function
|
||||
end module
|
@ -0,0 +1,20 @@
|
||||
module gh23879
|
||||
implicit none
|
||||
private
|
||||
public :: foo
|
||||
|
||||
contains
|
||||
|
||||
subroutine foo(a, b)
|
||||
integer, intent(in) :: a
|
||||
integer, intent(out) :: b
|
||||
b = a
|
||||
call bar(b)
|
||||
end subroutine
|
||||
|
||||
subroutine bar(x)
|
||||
integer, intent(inout) :: x
|
||||
x = 2*x
|
||||
end subroutine
|
||||
|
||||
end module gh23879
|
@ -0,0 +1,13 @@
|
||||
subroutine gh2848( &
|
||||
! first 2 parameters
|
||||
par1, par2,&
|
||||
! last 2 parameters
|
||||
par3, par4)
|
||||
|
||||
integer, intent(in) :: par1, par2
|
||||
integer, intent(out) :: par3, par4
|
||||
|
||||
par3 = par1
|
||||
par4 = par2
|
||||
|
||||
end subroutine gh2848
|
@ -0,0 +1,49 @@
|
||||
module foo
|
||||
type bar
|
||||
character(len = 32) :: item
|
||||
end type bar
|
||||
interface operator(.item.)
|
||||
module procedure item_int, item_real
|
||||
end interface operator(.item.)
|
||||
interface operator(==)
|
||||
module procedure items_are_equal
|
||||
end interface operator(==)
|
||||
interface assignment(=)
|
||||
module procedure get_int, get_real
|
||||
end interface assignment(=)
|
||||
contains
|
||||
function item_int(val) result(elem)
|
||||
integer, intent(in) :: val
|
||||
type(bar) :: elem
|
||||
|
||||
write(elem%item, "(I32)") val
|
||||
end function item_int
|
||||
|
||||
function item_real(val) result(elem)
|
||||
real, intent(in) :: val
|
||||
type(bar) :: elem
|
||||
|
||||
write(elem%item, "(1PE32.12)") val
|
||||
end function item_real
|
||||
|
||||
function items_are_equal(val1, val2) result(equal)
|
||||
type(bar), intent(in) :: val1, val2
|
||||
logical :: equal
|
||||
|
||||
equal = (val1%item == val2%item)
|
||||
end function items_are_equal
|
||||
|
||||
subroutine get_real(rval, item)
|
||||
real, intent(out) :: rval
|
||||
type(bar), intent(in) :: item
|
||||
|
||||
read(item%item, *) rval
|
||||
end subroutine get_real
|
||||
|
||||
subroutine get_int(rval, item)
|
||||
integer, intent(out) :: rval
|
||||
type(bar), intent(in) :: item
|
||||
|
||||
read(item%item, *) rval
|
||||
end subroutine get_int
|
||||
end module foo
|
@ -0,0 +1,11 @@
|
||||
module foo
|
||||
private
|
||||
integer :: a
|
||||
public :: setA
|
||||
integer :: b
|
||||
contains
|
||||
subroutine setA(v)
|
||||
integer, intent(in) :: v
|
||||
a = v
|
||||
end subroutine setA
|
||||
end module foo
|
@ -0,0 +1,10 @@
|
||||
module foo
|
||||
public
|
||||
integer, private :: a
|
||||
public :: setA
|
||||
contains
|
||||
subroutine setA(v)
|
||||
integer, intent(in) :: v
|
||||
a = v
|
||||
end subroutine setA
|
||||
end module foo
|
@ -0,0 +1,10 @@
|
||||
module foo
|
||||
public
|
||||
integer, private :: a
|
||||
integer :: b
|
||||
contains
|
||||
subroutine setA(v)
|
||||
integer, intent(in) :: v
|
||||
a = v
|
||||
end subroutine setA
|
||||
end module foo
|
@ -0,0 +1,4 @@
|
||||
subroutine foo(x)
|
||||
real(8), intent(in) :: x
|
||||
! Écrit à l'écran la valeur de x
|
||||
end subroutine
|
@ -0,0 +1 @@
|
||||
dict(real=dict(real32='float', real64='double'), integer=dict(int64='long_long'))
|
@ -0,0 +1,9 @@
|
||||
subroutine func1(n, x, res)
|
||||
use, intrinsic :: iso_fortran_env, only: int64, real64
|
||||
implicit none
|
||||
integer(int64), intent(in) :: n
|
||||
real(real64), intent(in) :: x(n)
|
||||
real(real64), intent(out) :: res
|
||||
!f2py intent(hide) :: n
|
||||
res = sum(x)
|
||||
end
|
@ -0,0 +1,34 @@
|
||||
module coddity
|
||||
use iso_c_binding, only: c_double, c_int, c_int64_t
|
||||
implicit none
|
||||
contains
|
||||
subroutine c_add(a, b, c) bind(c, name="c_add")
|
||||
real(c_double), intent(in) :: a, b
|
||||
real(c_double), intent(out) :: c
|
||||
c = a + b
|
||||
end subroutine c_add
|
||||
! gh-9693
|
||||
function wat(x, y) result(z) bind(c)
|
||||
integer(c_int), intent(in) :: x, y
|
||||
integer(c_int) :: z
|
||||
|
||||
z = x + 7
|
||||
end function wat
|
||||
! gh-25207
|
||||
subroutine c_add_int64(a, b, c) bind(c)
|
||||
integer(c_int64_t), intent(in) :: a, b
|
||||
integer(c_int64_t), intent(out) :: c
|
||||
c = a + b
|
||||
end subroutine c_add_int64
|
||||
! gh-25207
|
||||
subroutine add_arr(A, B, C)
|
||||
integer(c_int64_t), intent(in) :: A(3)
|
||||
integer(c_int64_t), intent(in) :: B(3)
|
||||
integer(c_int64_t), intent(out) :: C(3)
|
||||
integer :: j
|
||||
|
||||
do j = 1, 3
|
||||
C(j) = A(j)+B(j)
|
||||
end do
|
||||
end subroutine
|
||||
end module coddity
|
@ -0,0 +1,20 @@
|
||||
|
||||
|
||||
subroutine selectedrealkind(p, r, res)
|
||||
implicit none
|
||||
|
||||
integer, intent(in) :: p, r
|
||||
!f2py integer :: r=0
|
||||
integer, intent(out) :: res
|
||||
res = selected_real_kind(p, r)
|
||||
|
||||
end subroutine
|
||||
|
||||
subroutine selectedintkind(p, res)
|
||||
implicit none
|
||||
|
||||
integer, intent(in) :: p
|
||||
integer, intent(out) :: res
|
||||
res = selected_int_kind(p)
|
||||
|
||||
end subroutine
|
@ -0,0 +1,5 @@
|
||||
subroutine bar11(a)
|
||||
cf2py intent(out) a
|
||||
integer a
|
||||
a = 11
|
||||
end
|
@ -0,0 +1,8 @@
|
||||
module foo_fixed
|
||||
contains
|
||||
subroutine bar12(a)
|
||||
!f2py intent(out) a
|
||||
integer a
|
||||
a = 12
|
||||
end subroutine bar12
|
||||
end module foo_fixed
|
@ -0,0 +1,8 @@
|
||||
module foo_free
|
||||
contains
|
||||
subroutine bar13(a)
|
||||
!f2py intent(out) a
|
||||
integer a
|
||||
a = 13
|
||||
end subroutine bar13
|
||||
end module foo_free
|
@ -0,0 +1,8 @@
|
||||
module data
|
||||
real(8) :: shift
|
||||
contains
|
||||
subroutine set_shift(in_shift)
|
||||
real(8), intent(in) :: in_shift
|
||||
shift = in_shift
|
||||
end subroutine set_shift
|
||||
end module data
|
@ -0,0 +1,6 @@
|
||||
subroutine shift_a(dim_a, a)
|
||||
use data, only: shift
|
||||
integer, intent(in) :: dim_a
|
||||
real(8), intent(inout), dimension(dim_a) :: a
|
||||
a = a + shift
|
||||
end subroutine shift_a
|
@ -0,0 +1,21 @@
|
||||
module mod2
|
||||
implicit none
|
||||
private mod2_func1
|
||||
contains
|
||||
|
||||
subroutine mod2_func1()
|
||||
print*, "mod2_func1"
|
||||
end subroutine mod2_func1
|
||||
|
||||
end module mod2
|
||||
|
||||
module mod1
|
||||
implicit none
|
||||
private :: mod1_func1
|
||||
contains
|
||||
|
||||
subroutine mod1_func1()
|
||||
print*, "mod1_func1"
|
||||
end subroutine mod1_func1
|
||||
|
||||
end module mod1
|
@ -0,0 +1,21 @@
|
||||
module mod2
|
||||
implicit none
|
||||
PUBLIC :: mod2_func1
|
||||
contains
|
||||
|
||||
subroutine mod2_func1()
|
||||
print*, "mod2_func1"
|
||||
end subroutine mod2_func1
|
||||
|
||||
end module mod2
|
||||
|
||||
module mod1
|
||||
implicit none
|
||||
PUBLIC :: mod1_func1
|
||||
contains
|
||||
|
||||
subroutine mod1_func1()
|
||||
print*, "mod1_func1"
|
||||
end subroutine mod1_func1
|
||||
|
||||
end module mod1
|
@ -0,0 +1,12 @@
|
||||
module mod
|
||||
integer :: i
|
||||
integer :: x(4)
|
||||
real, dimension(2,3) :: a
|
||||
real, allocatable, dimension(:,:) :: b
|
||||
contains
|
||||
subroutine foo
|
||||
integer :: k
|
||||
k = 1
|
||||
a(1,2) = a(1,2)+3
|
||||
end subroutine foo
|
||||
end module mod
|
@ -0,0 +1,20 @@
|
||||
module mathops
|
||||
implicit none
|
||||
contains
|
||||
function add(a, b) result(c)
|
||||
integer, intent(in) :: a, b
|
||||
integer :: c
|
||||
c = a + b
|
||||
end function add
|
||||
end module mathops
|
||||
|
||||
module useops
|
||||
use mathops, only: add
|
||||
implicit none
|
||||
contains
|
||||
function sum_and_double(a, b) result(d)
|
||||
integer, intent(in) :: a, b
|
||||
integer :: d
|
||||
d = 2 * add(a, b)
|
||||
end function sum_and_double
|
||||
end module useops
|
@ -0,0 +1,7 @@
|
||||
subroutine foo(is_, ie_, arr, tout)
|
||||
implicit none
|
||||
integer :: is_,ie_
|
||||
real, intent(in) :: arr(is_:ie_)
|
||||
real, intent(out) :: tout(is_:ie_)
|
||||
tout = arr
|
||||
end
|
@ -0,0 +1,45 @@
|
||||
! Check that parameter arrays are correctly intercepted.
|
||||
subroutine foo_array(x, y, z)
|
||||
implicit none
|
||||
integer, parameter :: dp = selected_real_kind(15)
|
||||
integer, parameter :: pa = 2
|
||||
integer, parameter :: intparamarray(2) = (/ 3, 5 /)
|
||||
integer, dimension(pa), parameter :: pb = (/ 2, 10 /)
|
||||
integer, parameter, dimension(intparamarray(1)) :: pc = (/ 2, 10, 20 /)
|
||||
real(dp), parameter :: doubleparamarray(3) = (/ 3.14_dp, 4._dp, 6.44_dp /)
|
||||
real(dp), intent(inout) :: x(intparamarray(1))
|
||||
real(dp), intent(inout) :: y(intparamarray(2))
|
||||
real(dp), intent(out) :: z
|
||||
|
||||
x = x/pb(2)
|
||||
y = y*pc(2)
|
||||
z = doubleparamarray(1)*doubleparamarray(2) + doubleparamarray(3)
|
||||
|
||||
return
|
||||
end subroutine
|
||||
|
||||
subroutine foo_array_any_index(x, y)
|
||||
implicit none
|
||||
integer, parameter :: dp = selected_real_kind(15)
|
||||
integer, parameter, dimension(-1:1) :: myparamarray = (/ 6, 3, 1 /)
|
||||
integer, parameter, dimension(2) :: nested = (/ 2, 0 /)
|
||||
integer, parameter :: dim = 2
|
||||
real(dp), intent(in) :: x(myparamarray(-1))
|
||||
real(dp), intent(out) :: y(nested(1), myparamarray(nested(dim)))
|
||||
|
||||
y = reshape(x, (/nested(1), myparamarray(nested(2))/))
|
||||
|
||||
return
|
||||
end subroutine
|
||||
|
||||
subroutine foo_array_delims(x)
|
||||
implicit none
|
||||
integer, parameter :: dp = selected_real_kind(15)
|
||||
integer, parameter, dimension(2) :: myparamarray = (/ (6), 1 /)
|
||||
integer, parameter, dimension(3) :: test = (/2, 1, (3)/)
|
||||
real(dp), intent(out) :: x
|
||||
|
||||
x = myparamarray(1)+test(3)
|
||||
|
||||
return
|
||||
end subroutine
|
@ -0,0 +1,57 @@
|
||||
! Check that parameters are correct intercepted.
|
||||
! Constants with comma separations are commonly
|
||||
! used, for instance Pi = 3._dp
|
||||
subroutine foo(x)
|
||||
implicit none
|
||||
integer, parameter :: sp = selected_real_kind(6)
|
||||
integer, parameter :: dp = selected_real_kind(15)
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
integer, parameter :: il = selected_int_kind(18)
|
||||
real(dp), intent(inout) :: x
|
||||
dimension x(3)
|
||||
real(sp), parameter :: three_s = 3._sp
|
||||
real(dp), parameter :: three_d = 3._dp
|
||||
integer(ii), parameter :: three_i = 3_ii
|
||||
integer(il), parameter :: three_l = 3_il
|
||||
x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
|
||||
x(2) = x(2) * three_s
|
||||
x(3) = x(3) * three_l
|
||||
return
|
||||
end subroutine
|
||||
|
||||
|
||||
subroutine foo_no(x)
|
||||
implicit none
|
||||
integer, parameter :: sp = selected_real_kind(6)
|
||||
integer, parameter :: dp = selected_real_kind(15)
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
integer, parameter :: il = selected_int_kind(18)
|
||||
real(dp), intent(inout) :: x
|
||||
dimension x(3)
|
||||
real(sp), parameter :: three_s = 3.
|
||||
real(dp), parameter :: three_d = 3.
|
||||
integer(ii), parameter :: three_i = 3
|
||||
integer(il), parameter :: three_l = 3
|
||||
x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
|
||||
x(2) = x(2) * three_s
|
||||
x(3) = x(3) * three_l
|
||||
return
|
||||
end subroutine
|
||||
|
||||
subroutine foo_sum(x)
|
||||
implicit none
|
||||
integer, parameter :: sp = selected_real_kind(6)
|
||||
integer, parameter :: dp = selected_real_kind(15)
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
integer, parameter :: il = selected_int_kind(18)
|
||||
real(dp), intent(inout) :: x
|
||||
dimension x(3)
|
||||
real(sp), parameter :: three_s = 2._sp + 1._sp
|
||||
real(dp), parameter :: three_d = 1._dp + 2._dp
|
||||
integer(ii), parameter :: three_i = 2_ii + 1_ii
|
||||
integer(il), parameter :: three_l = 1_il + 2_il
|
||||
x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
|
||||
x(2) = x(2) * three_s
|
||||
x(3) = x(3) * three_l
|
||||
return
|
||||
end subroutine
|
@ -0,0 +1,15 @@
|
||||
! Check that parameters are correct intercepted.
|
||||
! Constants with comma separations are commonly
|
||||
! used, for instance Pi = 3._dp
|
||||
subroutine foo_compound_int(x)
|
||||
implicit none
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
integer(ii), intent(inout) :: x
|
||||
dimension x(3)
|
||||
integer(ii), parameter :: three = 3_ii
|
||||
integer(ii), parameter :: two = 2_ii
|
||||
integer(ii), parameter :: six = three * 1_ii * two
|
||||
|
||||
x(1) = x(1) + x(2) + x(3) * six
|
||||
return
|
||||
end subroutine
|
@ -0,0 +1,22 @@
|
||||
! Check that parameters are correct intercepted.
|
||||
! Constants with comma separations are commonly
|
||||
! used, for instance Pi = 3._dp
|
||||
subroutine foo_int(x)
|
||||
implicit none
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
integer(ii), intent(inout) :: x
|
||||
dimension x(3)
|
||||
integer(ii), parameter :: three = 3_ii
|
||||
x(1) = x(1) + x(2) + x(3) * three
|
||||
return
|
||||
end subroutine
|
||||
|
||||
subroutine foo_long(x)
|
||||
implicit none
|
||||
integer, parameter :: ii = selected_int_kind(18)
|
||||
integer(ii), intent(inout) :: x
|
||||
dimension x(3)
|
||||
integer(ii), parameter :: three = 3_ii
|
||||
x(1) = x(1) + x(2) + x(3) * three
|
||||
return
|
||||
end subroutine
|
@ -0,0 +1,23 @@
|
||||
! Check that parameters are correct intercepted.
|
||||
! Specifically that types of constants without
|
||||
! compound kind specs are correctly inferred
|
||||
! adapted Gibbs iteration code from pymc
|
||||
! for this test case
|
||||
subroutine foo_non_compound_int(x)
|
||||
implicit none
|
||||
integer, parameter :: ii = selected_int_kind(9)
|
||||
|
||||
integer(ii) maxiterates
|
||||
parameter (maxiterates=2)
|
||||
|
||||
integer(ii) maxseries
|
||||
parameter (maxseries=2)
|
||||
|
||||
integer(ii) wasize
|
||||
parameter (wasize=maxiterates*maxseries)
|
||||
integer(ii), intent(inout) :: x
|
||||
dimension x(wasize)
|
||||
|
||||
x(1) = x(1) + x(2) + x(3) + x(4) * wasize
|
||||
return
|
||||
end subroutine
|
@ -0,0 +1,23 @@
|
||||
! Check that parameters are correct intercepted.
|
||||
! Constants with comma separations are commonly
|
||||
! used, for instance Pi = 3._dp
|
||||
subroutine foo_single(x)
|
||||
implicit none
|
||||
integer, parameter :: rp = selected_real_kind(6)
|
||||
real(rp), intent(inout) :: x
|
||||
dimension x(3)
|
||||
real(rp), parameter :: three = 3._rp
|
||||
x(1) = x(1) + x(2) + x(3) * three
|
||||
return
|
||||
end subroutine
|
||||
|
||||
subroutine foo_double(x)
|
||||
implicit none
|
||||
integer, parameter :: rp = selected_real_kind(15)
|
||||
real(rp), intent(inout) :: x
|
||||
dimension x(3)
|
||||
real(rp), parameter :: three = 3._rp
|
||||
x(1) = x(1) + x(2) + x(3) * three
|
||||
return
|
||||
end subroutine
|
||||
|
@ -0,0 +1,14 @@
|
||||
SUBROUTINE FOO(OUT1, OUT2, OUT3, OUT4, OUT5, OUT6)
|
||||
CHARACTER SINGLE, DOUBLE, SEMICOL, EXCLA, OPENPAR, CLOSEPAR
|
||||
PARAMETER (SINGLE="'", DOUBLE='"', SEMICOL=';', EXCLA="!",
|
||||
1 OPENPAR="(", CLOSEPAR=")")
|
||||
CHARACTER OUT1, OUT2, OUT3, OUT4, OUT5, OUT6
|
||||
Cf2py intent(out) OUT1, OUT2, OUT3, OUT4, OUT5, OUT6
|
||||
OUT1 = SINGLE
|
||||
OUT2 = DOUBLE
|
||||
OUT3 = SEMICOL
|
||||
OUT4 = EXCLA
|
||||
OUT5 = OPENPAR
|
||||
OUT6 = CLOSEPAR
|
||||
RETURN
|
||||
END
|
@ -0,0 +1 @@
|
||||
real(8) b, n, m
|
@ -0,0 +1,26 @@
|
||||
SUBROUTINE TESTSUB(
|
||||
& INPUT1, INPUT2, !Input
|
||||
& OUTPUT1, OUTPUT2) !Output
|
||||
|
||||
IMPLICIT NONE
|
||||
INTEGER, INTENT(IN) :: INPUT1, INPUT2
|
||||
INTEGER, INTENT(OUT) :: OUTPUT1, OUTPUT2
|
||||
|
||||
OUTPUT1 = INPUT1 + INPUT2
|
||||
OUTPUT2 = INPUT1 * INPUT2
|
||||
|
||||
RETURN
|
||||
END SUBROUTINE TESTSUB
|
||||
|
||||
SUBROUTINE TESTSUB2(OUTPUT)
|
||||
IMPLICIT NONE
|
||||
INTEGER, PARAMETER :: N = 10 ! Array dimension
|
||||
REAL, INTENT(OUT) :: OUTPUT(N)
|
||||
INTEGER :: I
|
||||
|
||||
DO I = 1, N
|
||||
OUTPUT(I) = I * 2.0
|
||||
END DO
|
||||
|
||||
RETURN
|
||||
END
|
@ -0,0 +1,5 @@
|
||||
C This is an invalid file, but it does compile with -ffixed-form
|
||||
subroutine mwe(
|
||||
& x)
|
||||
real x
|
||||
end subroutine mwe
|
@ -0,0 +1,9 @@
|
||||
SUBROUTINE TESTSUB(INPUT1, & ! Hello
|
||||
! commenty
|
||||
INPUT2, OUTPUT1, OUTPUT2) ! more comments
|
||||
INTEGER, INTENT(IN) :: INPUT1, INPUT2
|
||||
INTEGER, INTENT(OUT) :: OUTPUT1, OUTPUT2
|
||||
OUTPUT1 = INPUT1 + &
|
||||
INPUT2
|
||||
OUTPUT2 = INPUT1 * INPUT2
|
||||
END SUBROUTINE TESTSUB
|
@ -0,0 +1,5 @@
|
||||
function add(n,m) result(b)
|
||||
implicit none
|
||||
include 'AB.inc'
|
||||
b = n + m
|
||||
end function add
|
@ -0,0 +1,9 @@
|
||||
! Check that intent(in out) translates as intent(inout).
|
||||
! The separation seems to be a common usage.
|
||||
subroutine foo(x)
|
||||
implicit none
|
||||
real(4), intent(in out) :: x
|
||||
dimension x(3)
|
||||
x(1) = x(1) + x(2) + x(3)
|
||||
return
|
||||
end
|
@ -0,0 +1,45 @@
|
||||
function t0(value)
|
||||
character value
|
||||
character t0
|
||||
t0 = value
|
||||
end
|
||||
function t1(value)
|
||||
character*1 value
|
||||
character*1 t1
|
||||
t1 = value
|
||||
end
|
||||
function t5(value)
|
||||
character*5 value
|
||||
character*5 t5
|
||||
t5 = value
|
||||
end
|
||||
function ts(value)
|
||||
character*(*) value
|
||||
character*(*) ts
|
||||
ts = value
|
||||
end
|
||||
|
||||
subroutine s0(t0,value)
|
||||
character value
|
||||
character t0
|
||||
cf2py intent(out) t0
|
||||
t0 = value
|
||||
end
|
||||
subroutine s1(t1,value)
|
||||
character*1 value
|
||||
character*1 t1
|
||||
cf2py intent(out) t1
|
||||
t1 = value
|
||||
end
|
||||
subroutine s5(t5,value)
|
||||
character*5 value
|
||||
character*5 t5
|
||||
cf2py intent(out) t5
|
||||
t5 = value
|
||||
end
|
||||
subroutine ss(ts,value)
|
||||
character*(*) value
|
||||
character*10 ts
|
||||
cf2py intent(out) ts
|
||||
ts = value
|
||||
end
|
@ -0,0 +1,48 @@
|
||||
module f90_return_char
|
||||
contains
|
||||
function t0(value)
|
||||
character :: value
|
||||
character :: t0
|
||||
t0 = value
|
||||
end function t0
|
||||
function t1(value)
|
||||
character(len=1) :: value
|
||||
character(len=1) :: t1
|
||||
t1 = value
|
||||
end function t1
|
||||
function t5(value)
|
||||
character(len=5) :: value
|
||||
character(len=5) :: t5
|
||||
t5 = value
|
||||
end function t5
|
||||
function ts(value)
|
||||
character(len=*) :: value
|
||||
character(len=10) :: ts
|
||||
ts = value
|
||||
end function ts
|
||||
|
||||
subroutine s0(t0,value)
|
||||
character :: value
|
||||
character :: t0
|
||||
!f2py intent(out) t0
|
||||
t0 = value
|
||||
end subroutine s0
|
||||
subroutine s1(t1,value)
|
||||
character(len=1) :: value
|
||||
character(len=1) :: t1
|
||||
!f2py intent(out) t1
|
||||
t1 = value
|
||||
end subroutine s1
|
||||
subroutine s5(t5,value)
|
||||
character(len=5) :: value
|
||||
character(len=5) :: t5
|
||||
!f2py intent(out) t5
|
||||
t5 = value
|
||||
end subroutine s5
|
||||
subroutine ss(ts,value)
|
||||
character(len=*) :: value
|
||||
character(len=10) :: ts
|
||||
!f2py intent(out) ts
|
||||
ts = value
|
||||
end subroutine ss
|
||||
end module f90_return_char
|
@ -0,0 +1,45 @@
|
||||
function t0(value)
|
||||
complex value
|
||||
complex t0
|
||||
t0 = value
|
||||
end
|
||||
function t8(value)
|
||||
complex*8 value
|
||||
complex*8 t8
|
||||
t8 = value
|
||||
end
|
||||
function t16(value)
|
||||
complex*16 value
|
||||
complex*16 t16
|
||||
t16 = value
|
||||
end
|
||||
function td(value)
|
||||
double complex value
|
||||
double complex td
|
||||
td = value
|
||||
end
|
||||
|
||||
subroutine s0(t0,value)
|
||||
complex value
|
||||
complex t0
|
||||
cf2py intent(out) t0
|
||||
t0 = value
|
||||
end
|
||||
subroutine s8(t8,value)
|
||||
complex*8 value
|
||||
complex*8 t8
|
||||
cf2py intent(out) t8
|
||||
t8 = value
|
||||
end
|
||||
subroutine s16(t16,value)
|
||||
complex*16 value
|
||||
complex*16 t16
|
||||
cf2py intent(out) t16
|
||||
t16 = value
|
||||
end
|
||||
subroutine sd(td,value)
|
||||
double complex value
|
||||
double complex td
|
||||
cf2py intent(out) td
|
||||
td = value
|
||||
end
|
@ -0,0 +1,48 @@
|
||||
module f90_return_complex
|
||||
contains
|
||||
function t0(value)
|
||||
complex :: value
|
||||
complex :: t0
|
||||
t0 = value
|
||||
end function t0
|
||||
function t8(value)
|
||||
complex(kind=4) :: value
|
||||
complex(kind=4) :: t8
|
||||
t8 = value
|
||||
end function t8
|
||||
function t16(value)
|
||||
complex(kind=8) :: value
|
||||
complex(kind=8) :: t16
|
||||
t16 = value
|
||||
end function t16
|
||||
function td(value)
|
||||
double complex :: value
|
||||
double complex :: td
|
||||
td = value
|
||||
end function td
|
||||
|
||||
subroutine s0(t0,value)
|
||||
complex :: value
|
||||
complex :: t0
|
||||
!f2py intent(out) t0
|
||||
t0 = value
|
||||
end subroutine s0
|
||||
subroutine s8(t8,value)
|
||||
complex(kind=4) :: value
|
||||
complex(kind=4) :: t8
|
||||
!f2py intent(out) t8
|
||||
t8 = value
|
||||
end subroutine s8
|
||||
subroutine s16(t16,value)
|
||||
complex(kind=8) :: value
|
||||
complex(kind=8) :: t16
|
||||
!f2py intent(out) t16
|
||||
t16 = value
|
||||
end subroutine s16
|
||||
subroutine sd(td,value)
|
||||
double complex :: value
|
||||
double complex :: td
|
||||
!f2py intent(out) td
|
||||
td = value
|
||||
end subroutine sd
|
||||
end module f90_return_complex
|
@ -0,0 +1,56 @@
|
||||
function t0(value)
|
||||
integer value
|
||||
integer t0
|
||||
t0 = value
|
||||
end
|
||||
function t1(value)
|
||||
integer*1 value
|
||||
integer*1 t1
|
||||
t1 = value
|
||||
end
|
||||
function t2(value)
|
||||
integer*2 value
|
||||
integer*2 t2
|
||||
t2 = value
|
||||
end
|
||||
function t4(value)
|
||||
integer*4 value
|
||||
integer*4 t4
|
||||
t4 = value
|
||||
end
|
||||
function t8(value)
|
||||
integer*8 value
|
||||
integer*8 t8
|
||||
t8 = value
|
||||
end
|
||||
|
||||
subroutine s0(t0,value)
|
||||
integer value
|
||||
integer t0
|
||||
cf2py intent(out) t0
|
||||
t0 = value
|
||||
end
|
||||
subroutine s1(t1,value)
|
||||
integer*1 value
|
||||
integer*1 t1
|
||||
cf2py intent(out) t1
|
||||
t1 = value
|
||||
end
|
||||
subroutine s2(t2,value)
|
||||
integer*2 value
|
||||
integer*2 t2
|
||||
cf2py intent(out) t2
|
||||
t2 = value
|
||||
end
|
||||
subroutine s4(t4,value)
|
||||
integer*4 value
|
||||
integer*4 t4
|
||||
cf2py intent(out) t4
|
||||
t4 = value
|
||||
end
|
||||
subroutine s8(t8,value)
|
||||
integer*8 value
|
||||
integer*8 t8
|
||||
cf2py intent(out) t8
|
||||
t8 = value
|
||||
end
|
@ -0,0 +1,59 @@
|
||||
module f90_return_integer
|
||||
contains
|
||||
function t0(value)
|
||||
integer :: value
|
||||
integer :: t0
|
||||
t0 = value
|
||||
end function t0
|
||||
function t1(value)
|
||||
integer(kind=1) :: value
|
||||
integer(kind=1) :: t1
|
||||
t1 = value
|
||||
end function t1
|
||||
function t2(value)
|
||||
integer(kind=2) :: value
|
||||
integer(kind=2) :: t2
|
||||
t2 = value
|
||||
end function t2
|
||||
function t4(value)
|
||||
integer(kind=4) :: value
|
||||
integer(kind=4) :: t4
|
||||
t4 = value
|
||||
end function t4
|
||||
function t8(value)
|
||||
integer(kind=8) :: value
|
||||
integer(kind=8) :: t8
|
||||
t8 = value
|
||||
end function t8
|
||||
|
||||
subroutine s0(t0,value)
|
||||
integer :: value
|
||||
integer :: t0
|
||||
!f2py intent(out) t0
|
||||
t0 = value
|
||||
end subroutine s0
|
||||
subroutine s1(t1,value)
|
||||
integer(kind=1) :: value
|
||||
integer(kind=1) :: t1
|
||||
!f2py intent(out) t1
|
||||
t1 = value
|
||||
end subroutine s1
|
||||
subroutine s2(t2,value)
|
||||
integer(kind=2) :: value
|
||||
integer(kind=2) :: t2
|
||||
!f2py intent(out) t2
|
||||
t2 = value
|
||||
end subroutine s2
|
||||
subroutine s4(t4,value)
|
||||
integer(kind=4) :: value
|
||||
integer(kind=4) :: t4
|
||||
!f2py intent(out) t4
|
||||
t4 = value
|
||||
end subroutine s4
|
||||
subroutine s8(t8,value)
|
||||
integer(kind=8) :: value
|
||||
integer(kind=8) :: t8
|
||||
!f2py intent(out) t8
|
||||
t8 = value
|
||||
end subroutine s8
|
||||
end module f90_return_integer
|
@ -0,0 +1,56 @@
|
||||
function t0(value)
|
||||
logical value
|
||||
logical t0
|
||||
t0 = value
|
||||
end
|
||||
function t1(value)
|
||||
logical*1 value
|
||||
logical*1 t1
|
||||
t1 = value
|
||||
end
|
||||
function t2(value)
|
||||
logical*2 value
|
||||
logical*2 t2
|
||||
t2 = value
|
||||
end
|
||||
function t4(value)
|
||||
logical*4 value
|
||||
logical*4 t4
|
||||
t4 = value
|
||||
end
|
||||
c function t8(value)
|
||||
c logical*8 value
|
||||
c logical*8 t8
|
||||
c t8 = value
|
||||
c end
|
||||
|
||||
subroutine s0(t0,value)
|
||||
logical value
|
||||
logical t0
|
||||
cf2py intent(out) t0
|
||||
t0 = value
|
||||
end
|
||||
subroutine s1(t1,value)
|
||||
logical*1 value
|
||||
logical*1 t1
|
||||
cf2py intent(out) t1
|
||||
t1 = value
|
||||
end
|
||||
subroutine s2(t2,value)
|
||||
logical*2 value
|
||||
logical*2 t2
|
||||
cf2py intent(out) t2
|
||||
t2 = value
|
||||
end
|
||||
subroutine s4(t4,value)
|
||||
logical*4 value
|
||||
logical*4 t4
|
||||
cf2py intent(out) t4
|
||||
t4 = value
|
||||
end
|
||||
c subroutine s8(t8,value)
|
||||
c logical*8 value
|
||||
c logical*8 t8
|
||||
cf2py intent(out) t8
|
||||
c t8 = value
|
||||
c end
|
@ -0,0 +1,59 @@
|
||||
module f90_return_logical
|
||||
contains
|
||||
function t0(value)
|
||||
logical :: value
|
||||
logical :: t0
|
||||
t0 = value
|
||||
end function t0
|
||||
function t1(value)
|
||||
logical(kind=1) :: value
|
||||
logical(kind=1) :: t1
|
||||
t1 = value
|
||||
end function t1
|
||||
function t2(value)
|
||||
logical(kind=2) :: value
|
||||
logical(kind=2) :: t2
|
||||
t2 = value
|
||||
end function t2
|
||||
function t4(value)
|
||||
logical(kind=4) :: value
|
||||
logical(kind=4) :: t4
|
||||
t4 = value
|
||||
end function t4
|
||||
function t8(value)
|
||||
logical(kind=8) :: value
|
||||
logical(kind=8) :: t8
|
||||
t8 = value
|
||||
end function t8
|
||||
|
||||
subroutine s0(t0,value)
|
||||
logical :: value
|
||||
logical :: t0
|
||||
!f2py intent(out) t0
|
||||
t0 = value
|
||||
end subroutine s0
|
||||
subroutine s1(t1,value)
|
||||
logical(kind=1) :: value
|
||||
logical(kind=1) :: t1
|
||||
!f2py intent(out) t1
|
||||
t1 = value
|
||||
end subroutine s1
|
||||
subroutine s2(t2,value)
|
||||
logical(kind=2) :: value
|
||||
logical(kind=2) :: t2
|
||||
!f2py intent(out) t2
|
||||
t2 = value
|
||||
end subroutine s2
|
||||
subroutine s4(t4,value)
|
||||
logical(kind=4) :: value
|
||||
logical(kind=4) :: t4
|
||||
!f2py intent(out) t4
|
||||
t4 = value
|
||||
end subroutine s4
|
||||
subroutine s8(t8,value)
|
||||
logical(kind=8) :: value
|
||||
logical(kind=8) :: t8
|
||||
!f2py intent(out) t8
|
||||
t8 = value
|
||||
end subroutine s8
|
||||
end module f90_return_logical
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user