This commit is contained in:
2025-09-07 22:09:54 +02:00
parent e1b817252c
commit 2fc0d000b6
7796 changed files with 2159515 additions and 933 deletions

View File

@ -0,0 +1,16 @@
import pytest
from numpy.testing import IS_EDITABLE, IS_WASM
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
)

View File

@ -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

View File

@ -0,0 +1,6 @@
module test
abstract interface
subroutine foo()
end subroutine
end interface
end module test

View File

@ -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

View File

@ -0,0 +1 @@
dict(real=dict(rk="double"))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,4 @@
module precision
integer, parameter :: rk = selected_real_kind(8)
integer, parameter :: ik = selected_real_kind(4)
end module

View File

@ -0,0 +1,6 @@
SUBROUTINE FOO()
INTEGER BAR(2, 3)
COMMON /BLOCK/ BAR
RETURN
END

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,18 @@
module utils
implicit none
contains
subroutine my_abort(message)
implicit none
character(len=*), intent(in) :: message
!f2py callstatement PyErr_SetString(PyExc_ValueError, message);f2py_success = 0;
!f2py callprotoargument char*
write(0,*) "THIS SHOULD NOT APPEAR"
stop 1
end subroutine my_abort
subroutine do_something(message)
!f2py intent(callback, hide) mypy_abort
character(len=*), intent(in) :: message
call mypy_abort(message)
end subroutine do_something
end module utils

View File

@ -0,0 +1,6 @@
python module test_22819
interface
subroutine hello()
end subroutine hello
end interface
end python module test_22819

View File

@ -0,0 +1,3 @@
SUBROUTINE HI
PRINT*, "HELLO WORLD"
END SUBROUTINE

View File

@ -0,0 +1,3 @@
function hi()
print*, "Hello World"
end function

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,17 @@
subroutine common_with_division
integer lmu,lb,lub,lpmin
parameter (lmu=1)
parameter (lb=20)
c crackfortran fails to parse this
c parameter (lub=(lb-1)*lmu+1)
c crackfortran can successfully parse this though
parameter (lub=lb*lmu-lmu+1)
parameter (lpmin=2)
c crackfortran fails to parse this correctly
c common /mortmp/ ctmp((lub*(lub+1)*(lub+1))/lpmin+1)
common /mortmp/ ctmp(lub/lpmin+1)
return
end

View File

@ -0,0 +1,8 @@
BLOCK DATA PARAM_INI
COMMON /MYCOM/ MYDATA
DATA MYDATA /0/
END
SUBROUTINE SUB1
COMMON /MYCOM/ MYDATA
MYDATA = MYDATA + 1
END

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,6 @@
module foo
type bar
character(len = 4) :: text
end type bar
type(bar), parameter :: abar = bar('abar')
end module foo

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,5 @@
SUBROUTINE EXAMPLE( )
IF( .TRUE. ) THEN
CALL DO_SOMETHING()
END IF ! ** .TRUE. **
END

View File

@ -0,0 +1,4 @@
integer function intproduct(a, b) result(res)
integer, intent(in) :: a, b
res = a*b
end function

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,12 @@
module utils
implicit none
contains
subroutine my_abort(message)
implicit none
character(len=*), intent(in) :: message
!f2py callstatement PyErr_SetString(PyExc_ValueError, message);f2py_success = 0;
!f2py callprotoargument char*
write(0,*) "THIS SHOULD NOT APPEAR"
stop 1
end subroutine my_abort
end module utils

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,4 @@
subroutine foo(x)
real(8), intent(in) :: x
! Écrit à l'écran la valeur de x
end subroutine

View File

@ -0,0 +1 @@
dict(real=dict(real32='float', real64='double'), integer=dict(int64='long_long'))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,5 @@
subroutine bar11(a)
cf2py intent(out) a
integer a
a = 11
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
real(8) b, n, m

View File

@ -0,0 +1,25 @@
MODULE MOD_TYPES
INTEGER, PARAMETER :: SP = SELECTED_REAL_KIND(6, 37)
INTEGER, PARAMETER :: DP = SELECTED_REAL_KIND(15, 307)
END MODULE
!
MODULE F_GLOBALS
USE MOD_TYPES
IMPLICIT NONE
INTEGER, PARAMETER :: N_MAX = 16
INTEGER, PARAMETER :: I_MAX = 18
INTEGER, PARAMETER :: J_MAX = 72
REAL(SP) :: XREF
END MODULE F_GLOBALS
!
SUBROUTINE DUMMY ()
!
USE F_GLOBALS
USE MOD_TYPES
IMPLICIT NONE
!
REAL(SP) :: MINIMAL
MINIMAL = 0.01*XREF
RETURN
!
END SUBROUTINE DUMMY

View File

@ -0,0 +1,17 @@
module datonly
implicit none
integer, parameter :: max_value = 100
real, dimension(:), allocatable :: data_array
end module datonly
module dat
implicit none
integer, parameter :: max_= 1009
end module dat
subroutine simple_subroutine(ain, aout)
use dat, only: max_
integer, intent(in) :: ain
integer, intent(out) :: aout
aout = ain + max_
end subroutine simple_subroutine

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,5 @@
function add(n,m) result(b)
implicit none
include 'AB.inc'
b = n + m
end function add

View File

@ -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

View File

@ -0,0 +1,5 @@
subroutine inquire_next(IU)
IMPLICIT NONE
integer :: IU
!f2py intent(in) IU
end subroutine

View File

@ -0,0 +1,23 @@
module mtypes
implicit none
integer, parameter :: value1 = 100
type :: master_data
integer :: idat = 200
end type master_data
type(master_data) :: masterdata
end module mtypes
subroutine no_type_subroutine(ain, aout)
use mtypes, only: value1
integer, intent(in) :: ain
integer, intent(out) :: aout
aout = ain + value1
end subroutine no_type_subroutine
subroutine type_subroutine(ain, aout)
use mtypes, only: masterdata
integer, intent(in) :: ain
integer, intent(out) :: aout
aout = ain + masterdata%idat
end subroutine type_subroutine

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,45 @@
function t0(value)
real value
real t0
t0 = value
end
function t4(value)
real*4 value
real*4 t4
t4 = value
end
function t8(value)
real*8 value
real*8 t8
t8 = value
end
function td(value)
double precision value
double precision td
td = value
end
subroutine s0(t0,value)
real value
real t0
cf2py intent(out) t0
t0 = value
end
subroutine s4(t4,value)
real*4 value
real*4 t4
cf2py intent(out) t4
t4 = value
end
subroutine s8(t8,value)
real*8 value
real*8 t8
cf2py intent(out) t8
t8 = value
end
subroutine sd(td,value)
double precision value
double precision td
cf2py intent(out) td
td = value
end

View File

@ -0,0 +1,48 @@
module f90_return_real
contains
function t0(value)
real :: value
real :: t0
t0 = value
end function t0
function t4(value)
real(kind=4) :: value
real(kind=4) :: t4
t4 = value
end function t4
function t8(value)
real(kind=8) :: value
real(kind=8) :: t8
t8 = value
end function t8
function td(value)
double precision :: value
double precision :: td
td = value
end function td
subroutine s0(t0,value)
real :: value
real :: t0
!f2py intent(out) t0
t0 = value
end subroutine s0
subroutine s4(t4,value)
real(kind=4) :: value
real(kind=4) :: t4
!f2py intent(out) t4
t4 = value
end subroutine s4
subroutine s8(t8,value)
real(kind=8) :: value
real(kind=8) :: t8
!f2py intent(out) t8
t8 = value
end subroutine s8
subroutine sd(td,value)
double precision :: value
double precision :: td
!f2py intent(out) td
td = value
end subroutine sd
end module f90_return_real

View File

@ -0,0 +1,5 @@
REAL*8 FUNCTION FUNCFORTRANNAME(A,B)
REAL*8 A, B
FUNCFORTRANNAME = A + B
RETURN
END FUNCTION

View File

@ -0,0 +1,11 @@
python module funcfortranname ! in
interface ! in :funcfortranname
function funcfortranname_default(a,b) ! in :funcfortranname:funcfortranname.f
fortranname funcfortranname
real*8 :: a
real*8 :: b
real*8 :: funcfortranname_default
real*8, intent(out) :: funcfortranname
end function funcfortranname_default
end interface
end python module funcfortranname

View File

@ -0,0 +1,4 @@
SUBROUTINE SUBROUT(A,B,C)
REAL*8 A, B, C
C = A + B
END SUBROUTINE

View File

@ -0,0 +1,10 @@
python module subrout ! in
interface ! in :subrout
subroutine subrout_default(a,b,c) ! in :subrout:subrout.f
fortranname subrout
real*8 :: a
real*8 :: b
real*8, intent(out) :: c
end subroutine subrout_default
end interface
end python module subrout

View File

@ -0,0 +1,44 @@
subroutine foo(a, n, m, b)
implicit none
real, intent(in) :: a(n, m)
integer, intent(in) :: n, m
real, intent(out) :: b(size(a, 1))
integer :: i
do i = 1, size(b)
b(i) = sum(a(i,:))
enddo
end subroutine
subroutine trans(x,y)
implicit none
real, intent(in), dimension(:,:) :: x
real, intent(out), dimension( size(x,2), size(x,1) ) :: y
integer :: N, M, i, j
N = size(x,1)
M = size(x,2)
DO i=1,N
do j=1,M
y(j,i) = x(i,j)
END DO
END DO
end subroutine trans
subroutine flatten(x,y)
implicit none
real, intent(in), dimension(:,:) :: x
real, intent(out), dimension( size(x) ) :: y
integer :: N, M, i, j, k
N = size(x,1)
M = size(x,2)
k = 1
DO i=1,N
do j=1,M
y(k) = x(i,j)
k = k + 1
END DO
END DO
end subroutine flatten

View File

@ -0,0 +1,29 @@
MODULE char_test
CONTAINS
SUBROUTINE change_strings(strings, n_strs, out_strings)
IMPLICIT NONE
! Inputs
INTEGER, INTENT(IN) :: n_strs
CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings
CHARACTER, INTENT(OUT), DIMENSION(2,n_strs) :: out_strings
!f2py INTEGER, INTENT(IN) :: n_strs
!f2py CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings
!f2py CHARACTER, INTENT(OUT), DIMENSION(2,n_strs) :: strings
! Misc.
INTEGER*4 :: j
DO j=1, n_strs
out_strings(1,j) = strings(1,j)
out_strings(2,j) = 'A'
END DO
END SUBROUTINE change_strings
END MODULE char_test

View File

@ -0,0 +1,34 @@
function sint(s) result(i)
implicit none
character(len=*) :: s
integer :: j, i
i = 0
do j=len(s), 1, -1
if (.not.((i.eq.0).and.(s(j:j).eq.' '))) then
i = i + ichar(s(j:j)) * 10 ** (j - 1)
endif
end do
return
end function sint
function test_in_bytes4(a) result (i)
implicit none
integer :: sint
character(len=4) :: a
integer :: i
i = sint(a)
a(1:1) = 'A'
return
end function test_in_bytes4
function test_inout_bytes4(a) result (i)
implicit none
integer :: sint
character(len=4), intent(inout) :: a
integer :: i
if (a(1:1).ne.' ') then
a(1:1) = 'E'
endif
i = sint(a)
return
end function test_inout_bytes4

View File

@ -0,0 +1,8 @@
SUBROUTINE GREET(NAME, GREETING)
CHARACTER NAME*(*), GREETING*(*)
CHARACTER*(50) MESSAGE
MESSAGE = 'Hello, ' // NAME // ', ' // GREETING
c$$$ PRINT *, MESSAGE
END SUBROUTINE GREET

View File

@ -0,0 +1,7 @@
subroutine string_inout_optional(output)
implicit none
character*(32), optional, intent(inout) :: output
if (present(output)) then
output="output string"
endif
end subroutine

View File

@ -0,0 +1,14 @@
subroutine charint(trans, info)
character, intent(in) :: trans
integer, intent(out) :: info
if (trans == 'N') then
info = 1
else if (trans == 'T') then
info = 2
else if (trans == 'C') then
info = 3
else
info = -1
end if
end subroutine charint

View File

@ -0,0 +1,12 @@
python module _char_handling_test
interface
subroutine charint(trans, info)
callstatement (*f2py_func)(&trans, &info)
callprotoargument char*, int*
character, intent(in), check(trans=='N'||trans=='T'||trans=='C') :: trans = 'N'
integer intent(out) :: info
end subroutine charint
end interface
end python module _char_handling_test

View File

@ -0,0 +1,12 @@
python module _char_handling_test
interface
subroutine charint(trans, info)
callstatement (*f2py_func)(&trans, &info)
callprotoargument char*, int*
character, intent(in), check(*trans=='N'||*trans=='T'||*trans=='C') :: trans = 'N'
integer intent(out) :: info
end subroutine charint
end interface
end python module _char_handling_test

View File

@ -0,0 +1,9 @@
MODULE string_test
character(len=8) :: string
character string77 * 8
character(len=12), dimension(5,7) :: strarr
character strarr77(5,7) * 12
END MODULE string_test

View File

@ -0,0 +1,12 @@
C FILE: STRING.F
SUBROUTINE FOO(A,B,C,D)
CHARACTER*5 A, B
CHARACTER*(*) C,D
Cf2py intent(in) a,c
Cf2py intent(inout) b,d
A(1:1) = 'A'
B(1:1) = 'B'
C(1:1) = 'C'
D(1:1) = 'D'
END
C END OF FILE STRING.F

View File

@ -0,0 +1,9 @@
module fortfuncs
implicit none
contains
subroutine square(x,y)
integer, intent(in), value :: x
integer, intent(out) :: y
y = x*x
end subroutine square
end module fortfuncs

View File

@ -0,0 +1,26 @@
import pytest
from numpy.f2py import crackfortran
from numpy.testing import IS_WASM
from . import util
@pytest.mark.skipif(IS_WASM, reason="Cannot start subprocess")
@pytest.mark.slow
class TestAbstractInterface(util.F2PyTest):
sources = [util.getpath("tests", "src", "abstract_interface", "foo.f90")]
skip = ["add1", "add2"]
def test_abstract_interface(self):
assert self.module.ops_module.foo(3, 5) == (8, 13)
def test_parse_abstract_interface(self):
# Test gh18403
fpath = util.getpath("tests", "src", "abstract_interface",
"gh18403_mod.f90")
mod = crackfortran.crackfortran([str(fpath)])
assert len(mod) == 1
assert len(mod[0]["body"]) == 1
assert mod[0]["body"][0]["block"] == "abstract interface"

View File

@ -0,0 +1,678 @@
import copy
import platform
import sys
from pathlib import Path
import pytest
import numpy as np
from numpy._core._type_aliases import c_names_dict as _c_names_dict
from . import util
wrap = None
# Extend core typeinfo with CHARACTER to test dtype('c')
c_names_dict = dict(
CHARACTER=np.dtype("c"),
**_c_names_dict
)
def get_testdir():
testroot = Path(__file__).resolve().parent / "src"
return testroot / "array_from_pyobj"
def setup_module():
"""
Build the required testing extension module
"""
global wrap
if wrap is None:
src = [
get_testdir() / "wrapmodule.c",
]
wrap = util.build_meson(src, module_name="test_array_from_pyobj_ext")
def flags_info(arr):
flags = wrap.array_attrs(arr)[6]
return flags2names(flags)
def flags2names(flags):
info = []
for flagname in [
"CONTIGUOUS",
"FORTRAN",
"OWNDATA",
"ENSURECOPY",
"ENSUREARRAY",
"ALIGNED",
"NOTSWAPPED",
"WRITEABLE",
"WRITEBACKIFCOPY",
"UPDATEIFCOPY",
"BEHAVED",
"BEHAVED_RO",
"CARRAY",
"FARRAY",
]:
if abs(flags) & getattr(wrap, flagname, 0):
info.append(flagname)
return info
class Intent:
def __init__(self, intent_list=[]):
self.intent_list = intent_list[:]
flags = 0
for i in intent_list:
if i == "optional":
flags |= wrap.F2PY_OPTIONAL
else:
flags |= getattr(wrap, "F2PY_INTENT_" + i.upper())
self.flags = flags
def __getattr__(self, name):
name = name.lower()
if name == "in_":
name = "in"
return self.__class__(self.intent_list + [name])
def __str__(self):
return f"intent({','.join(self.intent_list)})"
def __repr__(self):
return f"Intent({self.intent_list!r})"
def is_intent(self, *names):
return all(name in self.intent_list for name in names)
def is_intent_exact(self, *names):
return len(self.intent_list) == len(names) and self.is_intent(*names)
intent = Intent()
_type_names = [
"BOOL",
"BYTE",
"UBYTE",
"SHORT",
"USHORT",
"INT",
"UINT",
"LONG",
"ULONG",
"LONGLONG",
"ULONGLONG",
"FLOAT",
"DOUBLE",
"CFLOAT",
"STRING1",
"STRING5",
"CHARACTER",
]
_cast_dict = {"BOOL": ["BOOL"]}
_cast_dict["BYTE"] = _cast_dict["BOOL"] + ["BYTE"]
_cast_dict["UBYTE"] = _cast_dict["BOOL"] + ["UBYTE"]
_cast_dict["BYTE"] = ["BYTE"]
_cast_dict["UBYTE"] = ["UBYTE"]
_cast_dict["SHORT"] = _cast_dict["BYTE"] + ["UBYTE", "SHORT"]
_cast_dict["USHORT"] = _cast_dict["UBYTE"] + ["BYTE", "USHORT"]
_cast_dict["INT"] = _cast_dict["SHORT"] + ["USHORT", "INT"]
_cast_dict["UINT"] = _cast_dict["USHORT"] + ["SHORT", "UINT"]
_cast_dict["LONG"] = _cast_dict["INT"] + ["LONG"]
_cast_dict["ULONG"] = _cast_dict["UINT"] + ["ULONG"]
_cast_dict["LONGLONG"] = _cast_dict["LONG"] + ["LONGLONG"]
_cast_dict["ULONGLONG"] = _cast_dict["ULONG"] + ["ULONGLONG"]
_cast_dict["FLOAT"] = _cast_dict["SHORT"] + ["USHORT", "FLOAT"]
_cast_dict["DOUBLE"] = _cast_dict["INT"] + ["UINT", "FLOAT", "DOUBLE"]
_cast_dict["CFLOAT"] = _cast_dict["FLOAT"] + ["CFLOAT"]
_cast_dict['STRING1'] = ['STRING1']
_cast_dict['STRING5'] = ['STRING5']
_cast_dict['CHARACTER'] = ['CHARACTER']
# 32 bit system malloc typically does not provide the alignment required by
# 16 byte long double types this means the inout intent cannot be satisfied
# and several tests fail as the alignment flag can be randomly true or false
# when numpy gains an aligned allocator the tests could be enabled again
#
# Furthermore, on macOS ARM64, LONGDOUBLE is an alias for DOUBLE.
if ((np.intp().dtype.itemsize != 4 or np.clongdouble().dtype.alignment <= 8)
and sys.platform != "win32"
and (platform.system(), platform.processor()) != ("Darwin", "arm")):
_type_names.extend(["LONGDOUBLE", "CDOUBLE", "CLONGDOUBLE"])
_cast_dict["LONGDOUBLE"] = _cast_dict["LONG"] + [
"ULONG",
"FLOAT",
"DOUBLE",
"LONGDOUBLE",
]
_cast_dict["CLONGDOUBLE"] = _cast_dict["LONGDOUBLE"] + [
"CFLOAT",
"CDOUBLE",
"CLONGDOUBLE",
]
_cast_dict["CDOUBLE"] = _cast_dict["DOUBLE"] + ["CFLOAT", "CDOUBLE"]
class Type:
_type_cache = {}
def __new__(cls, name):
if isinstance(name, np.dtype):
dtype0 = name
name = None
for n, i in c_names_dict.items():
if not isinstance(i, type) and dtype0.type is i.type:
name = n
break
obj = cls._type_cache.get(name.upper(), None)
if obj is not None:
return obj
obj = object.__new__(cls)
obj._init(name)
cls._type_cache[name.upper()] = obj
return obj
def _init(self, name):
self.NAME = name.upper()
if self.NAME == 'CHARACTER':
info = c_names_dict[self.NAME]
self.type_num = wrap.NPY_STRING
self.elsize = 1
self.dtype = np.dtype('c')
elif self.NAME.startswith('STRING'):
info = c_names_dict[self.NAME[:6]]
self.type_num = wrap.NPY_STRING
self.elsize = int(self.NAME[6:] or 0)
self.dtype = np.dtype(f'S{self.elsize}')
else:
info = c_names_dict[self.NAME]
self.type_num = getattr(wrap, 'NPY_' + self.NAME)
self.elsize = info.itemsize
self.dtype = np.dtype(info.type)
assert self.type_num == info.num
self.type = info.type
self.dtypechar = info.char
def __repr__(self):
return (f"Type({self.NAME})|type_num={self.type_num},"
f" dtype={self.dtype},"
f" type={self.type}, elsize={self.elsize},"
f" dtypechar={self.dtypechar}")
def cast_types(self):
return [self.__class__(_m) for _m in _cast_dict[self.NAME]]
def all_types(self):
return [self.__class__(_m) for _m in _type_names]
def smaller_types(self):
bits = c_names_dict[self.NAME].alignment
types = []
for name in _type_names:
if c_names_dict[name].alignment < bits:
types.append(Type(name))
return types
def equal_types(self):
bits = c_names_dict[self.NAME].alignment
types = []
for name in _type_names:
if name == self.NAME:
continue
if c_names_dict[name].alignment == bits:
types.append(Type(name))
return types
def larger_types(self):
bits = c_names_dict[self.NAME].alignment
types = []
for name in _type_names:
if c_names_dict[name].alignment > bits:
types.append(Type(name))
return types
class Array:
def __repr__(self):
return (f'Array({self.type}, {self.dims}, {self.intent},'
f' {self.obj})|arr={self.arr}')
def __init__(self, typ, dims, intent, obj):
self.type = typ
self.dims = dims
self.intent = intent
self.obj_copy = copy.deepcopy(obj)
self.obj = obj
# arr.dtypechar may be different from typ.dtypechar
self.arr = wrap.call(typ.type_num,
typ.elsize,
dims, intent.flags, obj)
assert isinstance(self.arr, np.ndarray)
self.arr_attr = wrap.array_attrs(self.arr)
if len(dims) > 1:
if self.intent.is_intent("c"):
assert (intent.flags & wrap.F2PY_INTENT_C)
assert not self.arr.flags["FORTRAN"]
assert self.arr.flags["CONTIGUOUS"]
assert (not self.arr_attr[6] & wrap.FORTRAN)
else:
assert (not intent.flags & wrap.F2PY_INTENT_C)
assert self.arr.flags["FORTRAN"]
assert not self.arr.flags["CONTIGUOUS"]
assert (self.arr_attr[6] & wrap.FORTRAN)
if obj is None:
self.pyarr = None
self.pyarr_attr = None
return
if intent.is_intent("cache"):
assert isinstance(obj, np.ndarray), repr(type(obj))
self.pyarr = np.array(obj).reshape(*dims).copy()
else:
self.pyarr = np.array(
np.array(obj, dtype=typ.dtypechar).reshape(*dims),
order=(self.intent.is_intent("c") and "C") or "F",
)
assert self.pyarr.dtype == typ
self.pyarr.setflags(write=self.arr.flags["WRITEABLE"])
assert self.pyarr.flags["OWNDATA"], (obj, intent)
self.pyarr_attr = wrap.array_attrs(self.pyarr)
if len(dims) > 1:
if self.intent.is_intent("c"):
assert not self.pyarr.flags["FORTRAN"]
assert self.pyarr.flags["CONTIGUOUS"]
assert (not self.pyarr_attr[6] & wrap.FORTRAN)
else:
assert self.pyarr.flags["FORTRAN"]
assert not self.pyarr.flags["CONTIGUOUS"]
assert (self.pyarr_attr[6] & wrap.FORTRAN)
assert self.arr_attr[1] == self.pyarr_attr[1] # nd
assert self.arr_attr[2] == self.pyarr_attr[2] # dimensions
if self.arr_attr[1] <= 1:
assert self.arr_attr[3] == self.pyarr_attr[3], repr((
self.arr_attr[3],
self.pyarr_attr[3],
self.arr.tobytes(),
self.pyarr.tobytes(),
)) # strides
assert self.arr_attr[5][-2:] == self.pyarr_attr[5][-2:], repr((
self.arr_attr[5], self.pyarr_attr[5]
)) # descr
assert self.arr_attr[6] == self.pyarr_attr[6], repr((
self.arr_attr[6],
self.pyarr_attr[6],
flags2names(0 * self.arr_attr[6] - self.pyarr_attr[6]),
flags2names(self.arr_attr[6]),
intent,
)) # flags
if intent.is_intent("cache"):
assert self.arr_attr[5][3] >= self.type.elsize
else:
assert self.arr_attr[5][3] == self.type.elsize
assert (self.arr_equal(self.pyarr, self.arr))
if isinstance(self.obj, np.ndarray):
if typ.elsize == Type(obj.dtype).elsize:
if not intent.is_intent("copy") and self.arr_attr[1] <= 1:
assert self.has_shared_memory()
def arr_equal(self, arr1, arr2):
if arr1.shape != arr2.shape:
return False
return (arr1 == arr2).all()
def __str__(self):
return str(self.arr)
def has_shared_memory(self):
"""Check that created array shares data with input array."""
if self.obj is self.arr:
return True
if not isinstance(self.obj, np.ndarray):
return False
obj_attr = wrap.array_attrs(self.obj)
return obj_attr[0] == self.arr_attr[0]
class TestIntent:
def test_in_out(self):
assert str(intent.in_.out) == "intent(in,out)"
assert intent.in_.c.is_intent("c")
assert not intent.in_.c.is_intent_exact("c")
assert intent.in_.c.is_intent_exact("c", "in")
assert intent.in_.c.is_intent_exact("in", "c")
assert not intent.in_.is_intent("c")
class TestSharedMemory:
@pytest.fixture(autouse=True, scope="class", params=_type_names)
def setup_type(self, request):
request.cls.type = Type(request.param)
request.cls.array = lambda self, dims, intent, obj: Array(
Type(request.param), dims, intent, obj)
@property
def num2seq(self):
if self.type.NAME.startswith('STRING'):
elsize = self.type.elsize
return ['1' * elsize, '2' * elsize]
return [1, 2]
@property
def num23seq(self):
if self.type.NAME.startswith('STRING'):
elsize = self.type.elsize
return [['1' * elsize, '2' * elsize, '3' * elsize],
['4' * elsize, '5' * elsize, '6' * elsize]]
return [[1, 2, 3], [4, 5, 6]]
def test_in_from_2seq(self):
a = self.array([2], intent.in_, self.num2seq)
assert not a.has_shared_memory()
def test_in_from_2casttype(self):
for t in self.type.cast_types():
obj = np.array(self.num2seq, dtype=t.dtype)
a = self.array([len(self.num2seq)], intent.in_, obj)
if t.elsize == self.type.elsize:
assert a.has_shared_memory(), repr((self.type.dtype, t.dtype))
else:
assert not a.has_shared_memory()
@pytest.mark.parametrize("write", ["w", "ro"])
@pytest.mark.parametrize("order", ["C", "F"])
@pytest.mark.parametrize("inp", ["2seq", "23seq"])
def test_in_nocopy(self, write, order, inp):
"""Test if intent(in) array can be passed without copies"""
seq = getattr(self, "num" + inp)
obj = np.array(seq, dtype=self.type.dtype, order=order)
obj.setflags(write=(write == 'w'))
a = self.array(obj.shape,
((order == 'C' and intent.in_.c) or intent.in_), obj)
assert a.has_shared_memory()
def test_inout_2seq(self):
obj = np.array(self.num2seq, dtype=self.type.dtype)
a = self.array([len(self.num2seq)], intent.inout, obj)
assert a.has_shared_memory()
try:
a = self.array([2], intent.in_.inout, self.num2seq)
except TypeError as msg:
if not str(msg).startswith(
"failed to initialize intent(inout|inplace|cache) array"):
raise
else:
raise SystemError("intent(inout) should have failed on sequence")
def test_f_inout_23seq(self):
obj = np.array(self.num23seq, dtype=self.type.dtype, order="F")
shape = (len(self.num23seq), len(self.num23seq[0]))
a = self.array(shape, intent.in_.inout, obj)
assert a.has_shared_memory()
obj = np.array(self.num23seq, dtype=self.type.dtype, order="C")
shape = (len(self.num23seq), len(self.num23seq[0]))
try:
a = self.array(shape, intent.in_.inout, obj)
except ValueError as msg:
if not str(msg).startswith(
"failed to initialize intent(inout) array"):
raise
else:
raise SystemError(
"intent(inout) should have failed on improper array")
def test_c_inout_23seq(self):
obj = np.array(self.num23seq, dtype=self.type.dtype)
shape = (len(self.num23seq), len(self.num23seq[0]))
a = self.array(shape, intent.in_.c.inout, obj)
assert a.has_shared_memory()
def test_in_copy_from_2casttype(self):
for t in self.type.cast_types():
obj = np.array(self.num2seq, dtype=t.dtype)
a = self.array([len(self.num2seq)], intent.in_.copy, obj)
assert not a.has_shared_memory()
def test_c_in_from_23seq(self):
a = self.array(
[len(self.num23seq), len(self.num23seq[0])], intent.in_,
self.num23seq)
assert not a.has_shared_memory()
def test_in_from_23casttype(self):
for t in self.type.cast_types():
obj = np.array(self.num23seq, dtype=t.dtype)
a = self.array(
[len(self.num23seq), len(self.num23seq[0])], intent.in_, obj)
assert not a.has_shared_memory()
def test_f_in_from_23casttype(self):
for t in self.type.cast_types():
obj = np.array(self.num23seq, dtype=t.dtype, order="F")
a = self.array(
[len(self.num23seq), len(self.num23seq[0])], intent.in_, obj)
if t.elsize == self.type.elsize:
assert a.has_shared_memory()
else:
assert not a.has_shared_memory()
def test_c_in_from_23casttype(self):
for t in self.type.cast_types():
obj = np.array(self.num23seq, dtype=t.dtype)
a = self.array(
[len(self.num23seq), len(self.num23seq[0])], intent.in_.c, obj)
if t.elsize == self.type.elsize:
assert a.has_shared_memory()
else:
assert not a.has_shared_memory()
def test_f_copy_in_from_23casttype(self):
for t in self.type.cast_types():
obj = np.array(self.num23seq, dtype=t.dtype, order="F")
a = self.array(
[len(self.num23seq), len(self.num23seq[0])], intent.in_.copy,
obj)
assert not a.has_shared_memory()
def test_c_copy_in_from_23casttype(self):
for t in self.type.cast_types():
obj = np.array(self.num23seq, dtype=t.dtype)
a = self.array(
[len(self.num23seq), len(self.num23seq[0])], intent.in_.c.copy,
obj)
assert not a.has_shared_memory()
def test_in_cache_from_2casttype(self):
for t in self.type.all_types():
if t.elsize != self.type.elsize:
continue
obj = np.array(self.num2seq, dtype=t.dtype)
shape = (len(self.num2seq), )
a = self.array(shape, intent.in_.c.cache, obj)
assert a.has_shared_memory()
a = self.array(shape, intent.in_.cache, obj)
assert a.has_shared_memory()
obj = np.array(self.num2seq, dtype=t.dtype, order="F")
a = self.array(shape, intent.in_.c.cache, obj)
assert a.has_shared_memory()
a = self.array(shape, intent.in_.cache, obj)
assert a.has_shared_memory(), repr(t.dtype)
try:
a = self.array(shape, intent.in_.cache, obj[::-1])
except ValueError as msg:
if not str(msg).startswith(
"failed to initialize intent(cache) array"):
raise
else:
raise SystemError(
"intent(cache) should have failed on multisegmented array")
def test_in_cache_from_2casttype_failure(self):
for t in self.type.all_types():
if t.NAME == 'STRING':
# string elsize is 0, so skipping the test
continue
if t.elsize >= self.type.elsize:
continue
is_int = np.issubdtype(t.dtype, np.integer)
if is_int and int(self.num2seq[0]) > np.iinfo(t.dtype).max:
# skip test if num2seq would trigger an overflow error
continue
obj = np.array(self.num2seq, dtype=t.dtype)
shape = (len(self.num2seq), )
try:
self.array(shape, intent.in_.cache, obj) # Should succeed
except ValueError as msg:
if not str(msg).startswith(
"failed to initialize intent(cache) array"):
raise
else:
raise SystemError(
"intent(cache) should have failed on smaller array")
def test_cache_hidden(self):
shape = (2, )
a = self.array(shape, intent.cache.hide, None)
assert a.arr.shape == shape
shape = (2, 3)
a = self.array(shape, intent.cache.hide, None)
assert a.arr.shape == shape
shape = (-1, 3)
try:
a = self.array(shape, intent.cache.hide, None)
except ValueError as msg:
if not str(msg).startswith(
"failed to create intent(cache|hide)|optional array"):
raise
else:
raise SystemError(
"intent(cache) should have failed on undefined dimensions")
def test_hidden(self):
shape = (2, )
a = self.array(shape, intent.hide, None)
assert a.arr.shape == shape
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
shape = (2, 3)
a = self.array(shape, intent.hide, None)
assert a.arr.shape == shape
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
assert a.arr.flags["FORTRAN"] and not a.arr.flags["CONTIGUOUS"]
shape = (2, 3)
a = self.array(shape, intent.c.hide, None)
assert a.arr.shape == shape
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
assert not a.arr.flags["FORTRAN"] and a.arr.flags["CONTIGUOUS"]
shape = (-1, 3)
try:
a = self.array(shape, intent.hide, None)
except ValueError as msg:
if not str(msg).startswith(
"failed to create intent(cache|hide)|optional array"):
raise
else:
raise SystemError(
"intent(hide) should have failed on undefined dimensions")
def test_optional_none(self):
shape = (2, )
a = self.array(shape, intent.optional, None)
assert a.arr.shape == shape
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
shape = (2, 3)
a = self.array(shape, intent.optional, None)
assert a.arr.shape == shape
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
assert a.arr.flags["FORTRAN"] and not a.arr.flags["CONTIGUOUS"]
shape = (2, 3)
a = self.array(shape, intent.c.optional, None)
assert a.arr.shape == shape
assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
assert not a.arr.flags["FORTRAN"] and a.arr.flags["CONTIGUOUS"]
def test_optional_from_2seq(self):
obj = self.num2seq
shape = (len(obj), )
a = self.array(shape, intent.optional, obj)
assert a.arr.shape == shape
assert not a.has_shared_memory()
def test_optional_from_23seq(self):
obj = self.num23seq
shape = (len(obj), len(obj[0]))
a = self.array(shape, intent.optional, obj)
assert a.arr.shape == shape
assert not a.has_shared_memory()
a = self.array(shape, intent.optional.c, obj)
assert a.arr.shape == shape
assert not a.has_shared_memory()
def test_inplace(self):
obj = np.array(self.num23seq, dtype=self.type.dtype)
assert not obj.flags["FORTRAN"] and obj.flags["CONTIGUOUS"]
shape = obj.shape
a = self.array(shape, intent.inplace, obj)
assert obj[1][2] == a.arr[1][2], repr((obj, a.arr))
a.arr[1][2] = 54
assert obj[1][2] == a.arr[1][2] == np.array(54, dtype=self.type.dtype)
assert a.arr is obj
assert obj.flags["FORTRAN"] # obj attributes are changed inplace!
assert not obj.flags["CONTIGUOUS"]
def test_inplace_from_casttype(self):
for t in self.type.cast_types():
if t is self.type:
continue
obj = np.array(self.num23seq, dtype=t.dtype)
assert obj.dtype.type == t.type
assert obj.dtype.type is not self.type.type
assert not obj.flags["FORTRAN"] and obj.flags["CONTIGUOUS"]
shape = obj.shape
a = self.array(shape, intent.inplace, obj)
assert obj[1][2] == a.arr[1][2], repr((obj, a.arr))
a.arr[1][2] = 54
assert obj[1][2] == a.arr[1][2] == np.array(54,
dtype=self.type.dtype)
assert a.arr is obj
assert obj.flags["FORTRAN"] # obj attributes changed inplace!
assert not obj.flags["CONTIGUOUS"]
assert obj.dtype.type is self.type.type # obj changed inplace!

Some files were not shown because too many files have changed in this diff Show More