mirror of
https://github.com/aykhans/AzSuicideDataVisualization.git
synced 2025-07-06 07:52:33 +00:00
first commit
This commit is contained in:
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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;
|
||||
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,"iOiO|:wrap.call",\
|
||||
&type_num,&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 = array_from_pyobj(type_num,dims,rank,intent|F2PY_INTENT_OUT,arr_capi);
|
||||
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),
|
||||
PyArray_DESCR(arr)->alignment,
|
||||
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", NPY_NTYPES);
|
||||
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("UPDATEIFCOPY", NPY_ARRAY_UPDATEIFCOPY);
|
||||
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
|
||||
|
||||
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
|
11
.venv/Lib/site-packages/numpy/f2py/tests/src/common/block.f
Normal file
11
.venv/Lib/site-packages/numpy/f2py/tests/src/common/block.f
Normal 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
|
20
.venv/Lib/site-packages/numpy/f2py/tests/src/kind/foo.f90
Normal file
20
.venv/Lib/site-packages/numpy/f2py/tests/src/kind/foo.f90
Normal 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
|
5
.venv/Lib/site-packages/numpy/f2py/tests/src/mixed/foo.f
Normal file
5
.venv/Lib/site-packages/numpy/f2py/tests/src/mixed/foo.f
Normal file
@ -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
|
BIN
.venv/Lib/site-packages/numpy/f2py/tests/src/module_data/mod.mod
Normal file
BIN
.venv/Lib/site-packages/numpy/f2py/tests/src/module_data/mod.mod
Normal file
Binary file not shown.
@ -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,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,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
|
44
.venv/Lib/site-packages/numpy/f2py/tests/src/size/foo.f90
Normal file
44
.venv/Lib/site-packages/numpy/f2py/tests/src/size/foo.f90
Normal 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
|
29
.venv/Lib/site-packages/numpy/f2py/tests/src/string/char.f90
Normal file
29
.venv/Lib/site-packages/numpy/f2py/tests/src/string/char.f90
Normal 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
|
||||
|
@ -0,0 +1,66 @@
|
||||
import textwrap
|
||||
from . import util
|
||||
from numpy.f2py import crackfortran
|
||||
|
||||
|
||||
class TestAbstractInterface(util.F2PyTest):
|
||||
suffix = '.f90'
|
||||
|
||||
skip = ['add1', 'add2']
|
||||
|
||||
code = textwrap.dedent("""
|
||||
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
|
||||
""")
|
||||
|
||||
def test_abstract_interface(self):
|
||||
assert self.module.ops_module.foo(3, 5) == (8, 13)
|
||||
|
||||
def test_parse_abstract_interface(self, tmp_path):
|
||||
# Test gh18403
|
||||
f_path = tmp_path / "gh18403_mod.f90"
|
||||
with f_path.open('w') as ff:
|
||||
ff.write(textwrap.dedent("""\
|
||||
module test
|
||||
abstract interface
|
||||
subroutine foo()
|
||||
end subroutine
|
||||
end interface
|
||||
end module test
|
||||
"""))
|
||||
mod = crackfortran.crackfortran([str(f_path)])
|
||||
assert len(mod) == 1
|
||||
assert len(mod[0]['body']) == 1
|
||||
assert mod[0]['body'][0]['block'] == 'abstract interface'
|
@ -0,0 +1,596 @@
|
||||
import os
|
||||
import sys
|
||||
import copy
|
||||
import platform
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
|
||||
from numpy.testing import assert_, assert_equal
|
||||
from numpy.core.multiarray import typeinfo
|
||||
from . import util
|
||||
|
||||
wrap = None
|
||||
|
||||
|
||||
def setup_module():
|
||||
"""
|
||||
Build the required testing extension module
|
||||
|
||||
"""
|
||||
global wrap
|
||||
|
||||
# Check compiler availability first
|
||||
if not util.has_c_compiler():
|
||||
pytest.skip("No C compiler available")
|
||||
|
||||
if wrap is None:
|
||||
config_code = """
|
||||
config.add_extension('test_array_from_pyobj_ext',
|
||||
sources=['wrapmodule.c', 'fortranobject.c'],
|
||||
define_macros=[])
|
||||
"""
|
||||
d = os.path.dirname(__file__)
|
||||
src = [os.path.join(d, 'src', 'array_from_pyobj', 'wrapmodule.c'),
|
||||
os.path.join(d, '..', 'src', 'fortranobject.c'),
|
||||
os.path.join(d, '..', 'src', 'fortranobject.h')]
|
||||
wrap = util.build_module_distutils(src, config_code,
|
||||
'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 'intent(%s)' % (','.join(self.intent_list))
|
||||
|
||||
def __repr__(self):
|
||||
return 'Intent(%r)' % (self.intent_list)
|
||||
|
||||
def is_intent(self, *names):
|
||||
for name in names:
|
||||
if name not in self.intent_list:
|
||||
return False
|
||||
return True
|
||||
|
||||
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']
|
||||
|
||||
_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']
|
||||
|
||||
# 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 fals
|
||||
# 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 typeinfo.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()
|
||||
info = typeinfo[self.NAME]
|
||||
self.type_num = getattr(wrap, 'NPY_' + self.NAME)
|
||||
assert_equal(self.type_num, info.num)
|
||||
self.dtype = np.dtype(info.type)
|
||||
self.type = info.type
|
||||
self.elsize = info.bits / 8
|
||||
self.dtypechar = info.char
|
||||
|
||||
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 = typeinfo[self.NAME].alignment
|
||||
types = []
|
||||
for name in _type_names:
|
||||
if typeinfo[name].alignment < bits:
|
||||
types.append(Type(name))
|
||||
return types
|
||||
|
||||
def equal_types(self):
|
||||
bits = typeinfo[self.NAME].alignment
|
||||
types = []
|
||||
for name in _type_names:
|
||||
if name == self.NAME:
|
||||
continue
|
||||
if typeinfo[name].alignment == bits:
|
||||
types.append(Type(name))
|
||||
return types
|
||||
|
||||
def larger_types(self):
|
||||
bits = typeinfo[self.NAME].alignment
|
||||
types = []
|
||||
for name in _type_names:
|
||||
if typeinfo[name].alignment > bits:
|
||||
types.append(Type(name))
|
||||
return types
|
||||
|
||||
|
||||
class Array:
|
||||
|
||||
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, dims, intent.flags, obj)
|
||||
|
||||
assert_(isinstance(self.arr, np.ndarray), repr(type(self.arr)))
|
||||
|
||||
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'],
|
||||
repr((self.arr.flags, getattr(obj, 'flags', None))))
|
||||
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,
|
||||
repr((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,
|
||||
repr((self.arr_attr[5][3], self.type.elsize)))
|
||||
else:
|
||||
assert_(self.arr_attr[5][3] == self.type.elsize,
|
||||
repr((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_equal(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:
|
||||
num2seq = [1, 2]
|
||||
num23seq = [[1, 2, 3], [4, 5, 6]]
|
||||
|
||||
@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)
|
||||
|
||||
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(), repr(t.dtype))
|
||||
|
||||
@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(), repr(t.dtype))
|
||||
|
||||
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(), repr(t.dtype))
|
||||
|
||||
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(), repr(t.dtype))
|
||||
else:
|
||||
assert_(not a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
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(), repr(t.dtype))
|
||||
else:
|
||||
assert_(not a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
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(), repr(t.dtype))
|
||||
|
||||
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(), repr(t.dtype))
|
||||
|
||||
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(), repr(t.dtype))
|
||||
|
||||
a = self.array(shape, intent.in_.cache, obj)
|
||||
assert_(a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
obj = np.array(self.num2seq, dtype=t.dtype, order='F')
|
||||
a = self.array(shape, intent.in_.c.cache, obj)
|
||||
assert_(a.has_shared_memory(), repr(t.dtype))
|
||||
|
||||
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.elsize >= self.type.elsize:
|
||||
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), repr((obj, a.arr)))
|
||||
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), repr((obj, a.arr)))
|
||||
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!
|
@ -0,0 +1,53 @@
|
||||
import os
|
||||
import pytest
|
||||
import tempfile
|
||||
|
||||
from numpy.testing import assert_
|
||||
from . import util
|
||||
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
|
||||
class TestAssumedShapeSumExample(util.F2PyTest):
|
||||
sources = [_path('src', 'assumed_shape', 'foo_free.f90'),
|
||||
_path('src', 'assumed_shape', 'foo_use.f90'),
|
||||
_path('src', 'assumed_shape', 'precision.f90'),
|
||||
_path('src', 'assumed_shape', 'foo_mod.f90'),
|
||||
_path('src', 'assumed_shape', '.f2py_f2cmap'),
|
||||
]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_all(self):
|
||||
r = self.module.fsum([1, 2])
|
||||
assert_(r == 3, repr(r))
|
||||
r = self.module.sum([1, 2])
|
||||
assert_(r == 3, repr(r))
|
||||
r = self.module.sum_with_use([1, 2])
|
||||
assert_(r == 3, repr(r))
|
||||
|
||||
r = self.module.mod.sum([1, 2])
|
||||
assert_(r == 3, repr(r))
|
||||
r = self.module.mod.fsum([1, 2])
|
||||
assert_(r == 3, repr(r))
|
||||
|
||||
|
||||
class TestF2cmapOption(TestAssumedShapeSumExample):
|
||||
def setup(self):
|
||||
# Use a custom file name for .f2py_f2cmap
|
||||
self.sources = list(self.sources)
|
||||
f2cmap_src = self.sources.pop(-1)
|
||||
|
||||
self.f2cmap_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
with open(f2cmap_src, 'rb') as f:
|
||||
self.f2cmap_file.write(f.read())
|
||||
self.f2cmap_file.close()
|
||||
|
||||
self.sources.append(self.f2cmap_file.name)
|
||||
self.options = ["--f2cmap", self.f2cmap_file.name]
|
||||
|
||||
super().setup()
|
||||
|
||||
def teardown(self):
|
||||
os.unlink(self.f2cmap_file.name)
|
@ -0,0 +1,23 @@
|
||||
import sys
|
||||
import pytest
|
||||
from . import util
|
||||
|
||||
from numpy.testing import assert_equal, IS_PYPY
|
||||
|
||||
class TestBlockDocString(util.F2PyTest):
|
||||
code = """
|
||||
SUBROUTINE FOO()
|
||||
INTEGER BAR(2, 3)
|
||||
|
||||
COMMON /BLOCK/ BAR
|
||||
RETURN
|
||||
END
|
||||
"""
|
||||
|
||||
@pytest.mark.skipif(sys.platform=='win32',
|
||||
reason='Fails with MinGW64 Gfortran (Issue #9673)')
|
||||
@pytest.mark.xfail(IS_PYPY,
|
||||
reason="PyPy cannot modify tp_doc after PyType_Ready")
|
||||
def test_block_docstring(self):
|
||||
expected = "bar : 'i'-array(2,3)\n"
|
||||
assert_equal(self.module.block.__doc__, expected)
|
325
.venv/Lib/site-packages/numpy/f2py/tests/test_callback.py
Normal file
325
.venv/Lib/site-packages/numpy/f2py/tests/test_callback.py
Normal file
@ -0,0 +1,325 @@
|
||||
import math
|
||||
import textwrap
|
||||
import sys
|
||||
import pytest
|
||||
import threading
|
||||
import traceback
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_, assert_equal, IS_PYPY
|
||||
from . import util
|
||||
|
||||
|
||||
class TestF77Callback(util.F2PyTest):
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize('name', 't,t2'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(name)
|
||||
|
||||
@pytest.mark.xfail(IS_PYPY,
|
||||
reason="PyPy cannot modify tp_doc after PyType_Ready")
|
||||
def test_docstring(self):
|
||||
expected = textwrap.dedent("""\
|
||||
a = t(fun,[fun_extra_args])
|
||||
|
||||
Wrapper for ``t``.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fun : call-back function
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
fun_extra_args : input tuple, optional
|
||||
Default: ()
|
||||
|
||||
Returns
|
||||
-------
|
||||
a : int
|
||||
|
||||
Notes
|
||||
-----
|
||||
Call-back functions::
|
||||
|
||||
def fun(): return a
|
||||
Return objects:
|
||||
a : int
|
||||
""")
|
||||
assert_equal(self.module.t.__doc__, expected)
|
||||
|
||||
def check_function(self, name):
|
||||
t = getattr(self.module, name)
|
||||
r = t(lambda: 4)
|
||||
assert_(r == 4, repr(r))
|
||||
r = t(lambda a: 5, fun_extra_args=(6,))
|
||||
assert_(r == 5, repr(r))
|
||||
r = t(lambda a: a, fun_extra_args=(6,))
|
||||
assert_(r == 6, repr(r))
|
||||
r = t(lambda a: 5 + a, fun_extra_args=(7,))
|
||||
assert_(r == 12, repr(r))
|
||||
r = t(lambda a: math.degrees(a), fun_extra_args=(math.pi,))
|
||||
assert_(r == 180, repr(r))
|
||||
r = t(math.degrees, fun_extra_args=(math.pi,))
|
||||
assert_(r == 180, repr(r))
|
||||
|
||||
r = t(self.module.func, fun_extra_args=(6,))
|
||||
assert_(r == 17, repr(r))
|
||||
r = t(self.module.func0)
|
||||
assert_(r == 11, repr(r))
|
||||
r = t(self.module.func0._cpointer)
|
||||
assert_(r == 11, repr(r))
|
||||
|
||||
class A:
|
||||
|
||||
def __call__(self):
|
||||
return 7
|
||||
|
||||
def mth(self):
|
||||
return 9
|
||||
a = A()
|
||||
r = t(a)
|
||||
assert_(r == 7, repr(r))
|
||||
r = t(a.mth)
|
||||
assert_(r == 9, repr(r))
|
||||
|
||||
@pytest.mark.skipif(sys.platform=='win32',
|
||||
reason='Fails with MinGW64 Gfortran (Issue #9673)')
|
||||
def test_string_callback(self):
|
||||
|
||||
def callback(code):
|
||||
if code == 'r':
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
f = getattr(self.module, 'string_callback')
|
||||
r = f(callback)
|
||||
assert_(r == 0, repr(r))
|
||||
|
||||
@pytest.mark.skipif(sys.platform=='win32',
|
||||
reason='Fails with MinGW64 Gfortran (Issue #9673)')
|
||||
def test_string_callback_array(self):
|
||||
# See gh-10027
|
||||
cu = np.zeros((1, 8), 'S1')
|
||||
|
||||
def callback(cu, lencu):
|
||||
if cu.shape != (lencu, 8):
|
||||
return 1
|
||||
if cu.dtype != 'S1':
|
||||
return 2
|
||||
if not np.all(cu == b''):
|
||||
return 3
|
||||
return 0
|
||||
|
||||
f = getattr(self.module, 'string_callback_array')
|
||||
res = f(callback, cu, len(cu))
|
||||
assert_(res == 0, repr(res))
|
||||
|
||||
def test_threadsafety(self):
|
||||
# Segfaults if the callback handling is not threadsafe
|
||||
|
||||
errors = []
|
||||
|
||||
def cb():
|
||||
# Sleep here to make it more likely for another thread
|
||||
# to call their callback at the same time.
|
||||
time.sleep(1e-3)
|
||||
|
||||
# Check reentrancy
|
||||
r = self.module.t(lambda: 123)
|
||||
assert_(r == 123)
|
||||
|
||||
return 42
|
||||
|
||||
def runner(name):
|
||||
try:
|
||||
for j in range(50):
|
||||
r = self.module.t(cb)
|
||||
assert_(r == 42)
|
||||
self.check_function(name)
|
||||
except Exception:
|
||||
errors.append(traceback.format_exc())
|
||||
|
||||
threads = [threading.Thread(target=runner, args=(arg,))
|
||||
for arg in ("t", "t2") for n in range(20)]
|
||||
|
||||
for t in threads:
|
||||
t.start()
|
||||
|
||||
for t in threads:
|
||||
t.join()
|
||||
|
||||
errors = "\n\n".join(errors)
|
||||
if errors:
|
||||
raise AssertionError(errors)
|
||||
|
||||
def test_hidden_callback(self):
|
||||
try:
|
||||
self.module.hidden_callback(2)
|
||||
except Exception as msg:
|
||||
assert_(str(msg).startswith('Callback global_f not defined'))
|
||||
|
||||
try:
|
||||
self.module.hidden_callback2(2)
|
||||
except Exception as msg:
|
||||
assert_(str(msg).startswith('cb: Callback global_f not defined'))
|
||||
|
||||
self.module.global_f = lambda x: x + 1
|
||||
r = self.module.hidden_callback(2)
|
||||
assert_(r == 3)
|
||||
|
||||
self.module.global_f = lambda x: x + 2
|
||||
r = self.module.hidden_callback(2)
|
||||
assert_(r == 4)
|
||||
|
||||
del self.module.global_f
|
||||
try:
|
||||
self.module.hidden_callback(2)
|
||||
except Exception as msg:
|
||||
assert_(str(msg).startswith('Callback global_f not defined'))
|
||||
|
||||
self.module.global_f = lambda x=0: x + 3
|
||||
r = self.module.hidden_callback(2)
|
||||
assert_(r == 5)
|
||||
|
||||
# reproducer of gh18341
|
||||
r = self.module.hidden_callback2(2)
|
||||
assert_(r == 3)
|
||||
|
||||
|
||||
class TestF77CallbackPythonTLS(TestF77Callback):
|
||||
"""
|
||||
Callback tests using Python thread-local storage instead of
|
||||
compiler-provided
|
||||
"""
|
||||
options = ["-DF2PY_USE_PYTHON_TLS"]
|
||||
|
||||
|
||||
class TestF90Callback(util.F2PyTest):
|
||||
|
||||
suffix = '.f90'
|
||||
|
||||
code = textwrap.dedent(
|
||||
"""
|
||||
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
|
||||
""")
|
||||
|
||||
def test_gh17797(self):
|
||||
|
||||
def incr(x):
|
||||
return x + 123
|
||||
|
||||
y = np.array([1, 2, 3], dtype=np.int64)
|
||||
r = self.module.gh17797(incr, y)
|
||||
assert r == 123 + 1 + 2 + 3
|
||||
|
||||
|
||||
class TestGH18335(util.F2PyTest):
|
||||
"""The reproduction of the reported issue requires specific input that
|
||||
extensions may break the issue conditions, so the reproducer is
|
||||
implemented as a separate test class. Do not extend this test with
|
||||
other tests!
|
||||
"""
|
||||
|
||||
suffix = '.f90'
|
||||
|
||||
code = textwrap.dedent(
|
||||
"""
|
||||
! 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
|
||||
""")
|
||||
|
||||
def test_gh18335(self):
|
||||
|
||||
def foo(x):
|
||||
x[0] += 1
|
||||
|
||||
y = np.array([1, 2, 3], dtype=np.int8)
|
||||
r = self.module.gh18335(foo)
|
||||
assert r == 123 + 1
|
25
.venv/Lib/site-packages/numpy/f2py/tests/test_common.py
Normal file
25
.venv/Lib/site-packages/numpy/f2py/tests/test_common.py
Normal file
@ -0,0 +1,25 @@
|
||||
import os
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
from . import util
|
||||
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
class TestCommonBlock(util.F2PyTest):
|
||||
sources = [_path('src', 'common', 'block.f')]
|
||||
|
||||
@pytest.mark.skipif(sys.platform=='win32',
|
||||
reason='Fails with MinGW64 Gfortran (Issue #9673)')
|
||||
def test_common_block(self):
|
||||
self.module.initcb()
|
||||
assert_array_equal(self.module.block.long_bn,
|
||||
np.array(1.0, dtype=np.float64))
|
||||
assert_array_equal(self.module.block.string_bn,
|
||||
np.array('2', dtype='|S1'))
|
||||
assert_array_equal(self.module.block.ok,
|
||||
np.array(3, dtype=np.int32))
|
@ -0,0 +1,125 @@
|
||||
"""See https://github.com/numpy/numpy/pull/11937.
|
||||
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import uuid
|
||||
from importlib import import_module
|
||||
import pytest
|
||||
|
||||
import numpy.f2py
|
||||
|
||||
from numpy.testing import assert_equal
|
||||
from . import util
|
||||
|
||||
|
||||
def setup_module():
|
||||
if not util.has_c_compiler():
|
||||
pytest.skip("Needs C compiler")
|
||||
if not util.has_f77_compiler():
|
||||
pytest.skip('Needs FORTRAN 77 compiler')
|
||||
|
||||
|
||||
# extra_args can be a list (since gh-11937) or string.
|
||||
# also test absence of extra_args
|
||||
@pytest.mark.parametrize(
|
||||
"extra_args", [['--noopt', '--debug'], '--noopt --debug', '']
|
||||
)
|
||||
@pytest.mark.leaks_references(reason="Imported module seems never deleted.")
|
||||
def test_f2py_init_compile(extra_args):
|
||||
# flush through the f2py __init__ compile() function code path as a
|
||||
# crude test for input handling following migration from
|
||||
# exec_command() to subprocess.check_output() in gh-11937
|
||||
|
||||
# the Fortran 77 syntax requires 6 spaces before any commands, but
|
||||
# more space may be added/
|
||||
fsource = """
|
||||
integer function foo()
|
||||
foo = 10 + 5
|
||||
return
|
||||
end
|
||||
"""
|
||||
# use various helper functions in util.py to enable robust build /
|
||||
# compile and reimport cycle in test suite
|
||||
moddir = util.get_module_dir()
|
||||
modname = util.get_temp_module_name()
|
||||
|
||||
cwd = os.getcwd()
|
||||
target = os.path.join(moddir, str(uuid.uuid4()) + '.f')
|
||||
# try running compile() with and without a source_fn provided so
|
||||
# that the code path where a temporary file for writing Fortran
|
||||
# source is created is also explored
|
||||
for source_fn in [target, None]:
|
||||
# mimic the path changing behavior used by build_module() in
|
||||
# util.py, but don't actually use build_module() because it has
|
||||
# its own invocation of subprocess that circumvents the
|
||||
# f2py.compile code block under test
|
||||
try:
|
||||
os.chdir(moddir)
|
||||
ret_val = numpy.f2py.compile(
|
||||
fsource,
|
||||
modulename=modname,
|
||||
extra_args=extra_args,
|
||||
source_fn=source_fn
|
||||
)
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
# check for compile success return value
|
||||
assert_equal(ret_val, 0)
|
||||
|
||||
# we are not currently able to import the Python-Fortran
|
||||
# interface module on Windows / Appveyor, even though we do get
|
||||
# successful compilation on that platform with Python 3.x
|
||||
if sys.platform != 'win32':
|
||||
# check for sensible result of Fortran function; that means
|
||||
# we can import the module name in Python and retrieve the
|
||||
# result of the sum operation
|
||||
return_check = import_module(modname)
|
||||
calc_result = return_check.foo()
|
||||
assert_equal(calc_result, 15)
|
||||
# Removal from sys.modules, is not as such necessary. Even with
|
||||
# removal, the module (dict) stays alive.
|
||||
del sys.modules[modname]
|
||||
|
||||
|
||||
def test_f2py_init_compile_failure():
|
||||
# verify an appropriate integer status value returned by
|
||||
# f2py.compile() when invalid Fortran is provided
|
||||
ret_val = numpy.f2py.compile(b"invalid")
|
||||
assert_equal(ret_val, 1)
|
||||
|
||||
|
||||
def test_f2py_init_compile_bad_cmd():
|
||||
# verify that usage of invalid command in f2py.compile() returns
|
||||
# status value of 127 for historic consistency with exec_command()
|
||||
# error handling
|
||||
|
||||
# patch the sys Python exe path temporarily to induce an OSError
|
||||
# downstream NOTE: how bad of an idea is this patching?
|
||||
try:
|
||||
temp = sys.executable
|
||||
sys.executable = 'does not exist'
|
||||
|
||||
# the OSError should take precedence over invalid Fortran
|
||||
ret_val = numpy.f2py.compile(b"invalid")
|
||||
assert_equal(ret_val, 127)
|
||||
finally:
|
||||
sys.executable = temp
|
||||
|
||||
|
||||
@pytest.mark.parametrize('fsource',
|
||||
['program test_f2py\nend program test_f2py',
|
||||
b'program test_f2py\nend program test_f2py',])
|
||||
def test_compile_from_strings(tmpdir, fsource):
|
||||
# Make sure we can compile str and bytes gh-12796
|
||||
cwd = os.getcwd()
|
||||
try:
|
||||
os.chdir(str(tmpdir))
|
||||
ret_val = numpy.f2py.compile(
|
||||
fsource,
|
||||
modulename='test_compile_from_strings',
|
||||
extension='.f90')
|
||||
assert_equal(ret_val, 0)
|
||||
finally:
|
||||
os.chdir(cwd)
|
288
.venv/Lib/site-packages/numpy/f2py/tests/test_crackfortran.py
Normal file
288
.venv/Lib/site-packages/numpy/f2py/tests/test_crackfortran.py
Normal file
@ -0,0 +1,288 @@
|
||||
import pytest
|
||||
import numpy as np
|
||||
from numpy.testing import assert_array_equal, assert_equal
|
||||
from numpy.f2py.crackfortran import markinnerspaces
|
||||
from . import util
|
||||
from numpy.f2py import crackfortran
|
||||
import textwrap
|
||||
|
||||
|
||||
class TestNoSpace(util.F2PyTest):
|
||||
# issue gh-15035: add handling for endsubroutine, endfunction with no space
|
||||
# between "end" and the block name
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
def test_module(self):
|
||||
k = np.array([1, 2, 3], dtype=np.float64)
|
||||
w = np.array([1, 2, 3], dtype=np.float64)
|
||||
self.module.subb(k)
|
||||
assert_array_equal(k, w + 1)
|
||||
self.module.subc([w, k])
|
||||
assert_array_equal(k, w + 1)
|
||||
assert self.module.t0(23) == b'2'
|
||||
|
||||
|
||||
class TestPublicPrivate():
|
||||
|
||||
def test_defaultPrivate(self, tmp_path):
|
||||
f_path = tmp_path / "mod.f90"
|
||||
with f_path.open('w') as ff:
|
||||
ff.write(textwrap.dedent("""\
|
||||
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
|
||||
"""))
|
||||
mod = crackfortran.crackfortran([str(f_path)])
|
||||
assert len(mod) == 1
|
||||
mod = mod[0]
|
||||
assert 'private' in mod['vars']['a']['attrspec']
|
||||
assert 'public' not in mod['vars']['a']['attrspec']
|
||||
assert 'private' in mod['vars']['b']['attrspec']
|
||||
assert 'public' not in mod['vars']['b']['attrspec']
|
||||
assert 'private' not in mod['vars']['seta']['attrspec']
|
||||
assert 'public' in mod['vars']['seta']['attrspec']
|
||||
|
||||
def test_defaultPublic(self, tmp_path):
|
||||
f_path = tmp_path / "mod.f90"
|
||||
with f_path.open('w') as ff:
|
||||
ff.write(textwrap.dedent("""\
|
||||
module foo
|
||||
public
|
||||
integer, private :: a
|
||||
public :: setA
|
||||
contains
|
||||
subroutine setA(v)
|
||||
integer, intent(in) :: v
|
||||
a = v
|
||||
end subroutine setA
|
||||
end module foo
|
||||
"""))
|
||||
mod = crackfortran.crackfortran([str(f_path)])
|
||||
assert len(mod) == 1
|
||||
mod = mod[0]
|
||||
assert 'private' in mod['vars']['a']['attrspec']
|
||||
assert 'public' not in mod['vars']['a']['attrspec']
|
||||
assert 'private' not in mod['vars']['seta']['attrspec']
|
||||
assert 'public' in mod['vars']['seta']['attrspec']
|
||||
|
||||
|
||||
class TestExternal(util.F2PyTest):
|
||||
# issue gh-17859: add external attribute support
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
def test_external_as_statement(self):
|
||||
def incr(x):
|
||||
return x + 123
|
||||
r = self.module.external_as_statement(incr)
|
||||
assert r == 123
|
||||
|
||||
def test_external_as_attribute(self):
|
||||
def incr(x):
|
||||
return x + 123
|
||||
r = self.module.external_as_attribute(incr)
|
||||
assert r == 123
|
||||
|
||||
|
||||
class TestCrackFortran(util.F2PyTest):
|
||||
|
||||
suffix = '.f90'
|
||||
|
||||
code = textwrap.dedent("""
|
||||
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
|
||||
""")
|
||||
|
||||
def test_gh2848(self):
|
||||
r = self.module.gh2848(1, 2)
|
||||
assert r == (1, 2)
|
||||
|
||||
|
||||
class TestMarkinnerspaces():
|
||||
# issue #14118: markinnerspaces does not handle multiple quotations
|
||||
|
||||
def test_do_not_touch_normal_spaces(self):
|
||||
test_list = ["a ", " a", "a b c", "'abcdefghij'"]
|
||||
for i in test_list:
|
||||
assert_equal(markinnerspaces(i), i)
|
||||
|
||||
def test_one_relevant_space(self):
|
||||
assert_equal(markinnerspaces("a 'b c' \\\' \\\'"), "a 'b@_@c' \\' \\'")
|
||||
assert_equal(markinnerspaces(r'a "b c" \" \"'), r'a "b@_@c" \" \"')
|
||||
|
||||
def test_ignore_inner_quotes(self):
|
||||
assert_equal(markinnerspaces('a \'b c" " d\' e'),
|
||||
"a 'b@_@c\"@_@\"@_@d' e")
|
||||
assert_equal(markinnerspaces('a "b c\' \' d" e'),
|
||||
"a \"b@_@c'@_@'@_@d\" e")
|
||||
|
||||
def test_multiple_relevant_spaces(self):
|
||||
assert_equal(markinnerspaces("a 'b c' 'd e'"), "a 'b@_@c' 'd@_@e'")
|
||||
assert_equal(markinnerspaces(r'a "b c" "d e"'), r'a "b@_@c" "d@_@e"')
|
||||
|
||||
|
||||
class TestDimSpec(util.F2PyTest):
|
||||
"""This test suite tests various expressions that are used as dimension
|
||||
specifications.
|
||||
|
||||
There exists two usage cases where analyzing dimensions
|
||||
specifications are important.
|
||||
|
||||
In the first case, the size of output arrays must be defined based
|
||||
on the inputs to a Fortran function. Because Fortran supports
|
||||
arbitrary bases for indexing, for instance, `arr(lower:upper)`,
|
||||
f2py has to evaluate an expression `upper - lower + 1` where
|
||||
`lower` and `upper` are arbitrary expressions of input parameters.
|
||||
The evaluation is performed in C, so f2py has to translate Fortran
|
||||
expressions to valid C expressions (an alternative approach is
|
||||
that a developer specifies the corresponding C expressions in a
|
||||
.pyf file).
|
||||
|
||||
In the second case, when user provides an input array with a given
|
||||
size but some hidden parameters used in dimensions specifications
|
||||
need to be determined based on the input array size. This is a
|
||||
harder problem because f2py has to solve the inverse problem: find
|
||||
a parameter `p` such that `upper(p) - lower(p) + 1` equals to the
|
||||
size of input array. In the case when this equation cannot be
|
||||
solved (e.g. because the input array size is wrong), raise an
|
||||
error before calling the Fortran function (that otherwise would
|
||||
likely crash Python process when the size of input arrays is
|
||||
wrong). f2py currently supports this case only when the equation
|
||||
is linear with respect to unknown parameter.
|
||||
|
||||
"""
|
||||
|
||||
suffix = '.f90'
|
||||
|
||||
code_template = textwrap.dedent("""
|
||||
function get_arr_size_{count}(a, n) result (length)
|
||||
integer, intent(in) :: n
|
||||
integer, dimension({dimspec}), intent(out) :: a
|
||||
integer length
|
||||
length = size(a)
|
||||
end function
|
||||
|
||||
subroutine get_inv_arr_size_{count}(a, n)
|
||||
integer :: n
|
||||
! the value of n is computed in f2py wrapper
|
||||
!f2py intent(out) n
|
||||
integer, dimension({dimspec}), intent(in) :: a
|
||||
if (a({first}).gt.0) then
|
||||
print*, "a=", a
|
||||
endif
|
||||
end subroutine
|
||||
""")
|
||||
|
||||
linear_dimspecs = [
|
||||
"n", "2*n", "2:n", "n/2", "5 - n/2", "3*n:20", "n*(n+1):n*(n+5)",
|
||||
"2*n, n"
|
||||
]
|
||||
nonlinear_dimspecs = ["2*n:3*n*n+2*n"]
|
||||
all_dimspecs = linear_dimspecs + nonlinear_dimspecs
|
||||
|
||||
code = ''
|
||||
for count, dimspec in enumerate(all_dimspecs):
|
||||
lst = [(d.split(":")[0] if ":" in d else "1") for d in dimspec.split(',')]
|
||||
code += code_template.format(
|
||||
count=count,
|
||||
dimspec=dimspec,
|
||||
first=", ".join(lst),
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize('dimspec', all_dimspecs)
|
||||
def test_array_size(self, dimspec):
|
||||
|
||||
count = self.all_dimspecs.index(dimspec)
|
||||
get_arr_size = getattr(self.module, f'get_arr_size_{count}')
|
||||
|
||||
for n in [1, 2, 3, 4, 5]:
|
||||
sz, a = get_arr_size(n)
|
||||
assert a.size == sz
|
||||
|
||||
@pytest.mark.parametrize('dimspec', all_dimspecs)
|
||||
def test_inv_array_size(self, dimspec):
|
||||
|
||||
count = self.all_dimspecs.index(dimspec)
|
||||
get_arr_size = getattr(self.module, f'get_arr_size_{count}')
|
||||
get_inv_arr_size = getattr(self.module, f'get_inv_arr_size_{count}')
|
||||
|
||||
for n in [1, 2, 3, 4, 5]:
|
||||
sz, a = get_arr_size(n)
|
||||
if dimspec in self.nonlinear_dimspecs:
|
||||
# one must specify n as input, the call we'll ensure
|
||||
# that a and n are compatible:
|
||||
n1 = get_inv_arr_size(a, n)
|
||||
else:
|
||||
# in case of linear dependence, n can be determined
|
||||
# from the shape of a:
|
||||
n1 = get_inv_arr_size(a)
|
||||
# n1 may be different from n (for instance, when `a` size
|
||||
# is a function of some `n` fraction) but it must produce
|
||||
# the same sized array
|
||||
sz1, _ = get_arr_size(n1)
|
||||
assert sz == sz1, (n, n1, sz, sz1)
|
||||
|
||||
|
||||
class TestModuleDeclaration():
|
||||
def test_dependencies(self, tmp_path):
|
||||
f_path = tmp_path / "mod.f90"
|
||||
with f_path.open('w') as ff:
|
||||
ff.write(textwrap.dedent("""\
|
||||
module foo
|
||||
type bar
|
||||
character(len = 4) :: text
|
||||
end type bar
|
||||
type(bar), parameter :: abar = bar('abar')
|
||||
end module foo
|
||||
"""))
|
||||
mod = crackfortran.crackfortran([str(f_path)])
|
||||
assert len(mod) == 1
|
||||
assert mod[0]['vars']['abar']['='] == "bar('abar')"
|
32
.venv/Lib/site-packages/numpy/f2py/tests/test_kind.py
Normal file
32
.venv/Lib/site-packages/numpy/f2py/tests/test_kind.py
Normal file
@ -0,0 +1,32 @@
|
||||
import os
|
||||
import pytest
|
||||
|
||||
from numpy.testing import assert_
|
||||
from numpy.f2py.crackfortran import (
|
||||
_selected_int_kind_func as selected_int_kind,
|
||||
_selected_real_kind_func as selected_real_kind
|
||||
)
|
||||
from . import util
|
||||
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
|
||||
class TestKind(util.F2PyTest):
|
||||
sources = [_path('src', 'kind', 'foo.f90')]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_all(self):
|
||||
selectedrealkind = self.module.selectedrealkind
|
||||
selectedintkind = self.module.selectedintkind
|
||||
|
||||
for i in range(40):
|
||||
assert_(selectedintkind(i) in [selected_int_kind(i), -1],
|
||||
'selectedintkind(%s): expected %r but got %r' %
|
||||
(i, selected_int_kind(i), selectedintkind(i)))
|
||||
|
||||
for i in range(20):
|
||||
assert_(selectedrealkind(i) in [selected_real_kind(i), -1],
|
||||
'selectedrealkind(%s): expected %r but got %r' %
|
||||
(i, selected_real_kind(i), selectedrealkind(i)))
|
35
.venv/Lib/site-packages/numpy/f2py/tests/test_mixed.py
Normal file
35
.venv/Lib/site-packages/numpy/f2py/tests/test_mixed.py
Normal file
@ -0,0 +1,35 @@
|
||||
import os
|
||||
import textwrap
|
||||
import pytest
|
||||
|
||||
from numpy.testing import assert_, assert_equal, IS_PYPY
|
||||
from . import util
|
||||
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
|
||||
class TestMixed(util.F2PyTest):
|
||||
sources = [_path('src', 'mixed', 'foo.f'),
|
||||
_path('src', 'mixed', 'foo_fixed.f90'),
|
||||
_path('src', 'mixed', 'foo_free.f90')]
|
||||
|
||||
def test_all(self):
|
||||
assert_(self.module.bar11() == 11)
|
||||
assert_(self.module.foo_fixed.bar12() == 12)
|
||||
assert_(self.module.foo_free.bar13() == 13)
|
||||
|
||||
@pytest.mark.xfail(IS_PYPY,
|
||||
reason="PyPy cannot modify tp_doc after PyType_Ready")
|
||||
def test_docstring(self):
|
||||
expected = textwrap.dedent("""\
|
||||
a = bar11()
|
||||
|
||||
Wrapper for ``bar11``.
|
||||
|
||||
Returns
|
||||
-------
|
||||
a : int
|
||||
""")
|
||||
assert_equal(self.module.bar11.__doc__, expected)
|
30
.venv/Lib/site-packages/numpy/f2py/tests/test_module_doc.py
Normal file
30
.venv/Lib/site-packages/numpy/f2py/tests/test_module_doc.py
Normal file
@ -0,0 +1,30 @@
|
||||
import os
|
||||
import sys
|
||||
import pytest
|
||||
import textwrap
|
||||
|
||||
from . import util
|
||||
from numpy.testing import assert_equal, IS_PYPY
|
||||
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
|
||||
class TestModuleDocString(util.F2PyTest):
|
||||
sources = [_path('src', 'module_data', 'module_data_docstring.f90')]
|
||||
|
||||
@pytest.mark.skipif(sys.platform=='win32',
|
||||
reason='Fails with MinGW64 Gfortran (Issue #9673)')
|
||||
@pytest.mark.xfail(IS_PYPY,
|
||||
reason="PyPy cannot modify tp_doc after PyType_Ready")
|
||||
def test_module_docstring(self):
|
||||
assert_equal(self.module.mod.__doc__,
|
||||
textwrap.dedent('''\
|
||||
i : 'i'-scalar
|
||||
x : 'i'-array(4)
|
||||
a : 'f'-array(2,3)
|
||||
b : 'f'-array(-1,-1), not allocated\x00
|
||||
foo()\n
|
||||
Wrapper for ``foo``.\n\n''')
|
||||
)
|
116
.venv/Lib/site-packages/numpy/f2py/tests/test_parameter.py
Normal file
116
.venv/Lib/site-packages/numpy/f2py/tests/test_parameter.py
Normal file
@ -0,0 +1,116 @@
|
||||
import os
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_raises, assert_equal
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
|
||||
class TestParameters(util.F2PyTest):
|
||||
# Check that intent(in out) translates as intent(inout)
|
||||
sources = [_path('src', 'parameter', 'constant_real.f90'),
|
||||
_path('src', 'parameter', 'constant_integer.f90'),
|
||||
_path('src', 'parameter', 'constant_both.f90'),
|
||||
_path('src', 'parameter', 'constant_compound.f90'),
|
||||
_path('src', 'parameter', 'constant_non_compound.f90'),
|
||||
]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_constant_real_single(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.float32)[::2]
|
||||
assert_raises(ValueError, self.module.foo_single, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.float32)
|
||||
self.module.foo_single(x)
|
||||
assert_equal(x, [0 + 1 + 2*3, 1, 2])
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_constant_real_double(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.float64)[::2]
|
||||
assert_raises(ValueError, self.module.foo_double, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.float64)
|
||||
self.module.foo_double(x)
|
||||
assert_equal(x, [0 + 1 + 2*3, 1, 2])
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_constant_compound_int(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.int32)[::2]
|
||||
assert_raises(ValueError, self.module.foo_compound_int, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.int32)
|
||||
self.module.foo_compound_int(x)
|
||||
assert_equal(x, [0 + 1 + 2*6, 1, 2])
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_constant_non_compound_int(self):
|
||||
# check values
|
||||
x = np.arange(4, dtype=np.int32)
|
||||
self.module.foo_non_compound_int(x)
|
||||
assert_equal(x, [0 + 1 + 2 + 3*4, 1, 2, 3])
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_constant_integer_int(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.int32)[::2]
|
||||
assert_raises(ValueError, self.module.foo_int, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.int32)
|
||||
self.module.foo_int(x)
|
||||
assert_equal(x, [0 + 1 + 2*3, 1, 2])
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_constant_integer_long(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.int64)[::2]
|
||||
assert_raises(ValueError, self.module.foo_long, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.int64)
|
||||
self.module.foo_long(x)
|
||||
assert_equal(x, [0 + 1 + 2*3, 1, 2])
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_constant_both(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.float64)[::2]
|
||||
assert_raises(ValueError, self.module.foo, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.float64)
|
||||
self.module.foo(x)
|
||||
assert_equal(x, [0 + 1*3*3 + 2*3*3, 1*3, 2*3])
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_constant_no(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.float64)[::2]
|
||||
assert_raises(ValueError, self.module.foo_no, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.float64)
|
||||
self.module.foo_no(x)
|
||||
assert_equal(x, [0 + 1*3*3 + 2*3*3, 1*3, 2*3])
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_constant_sum(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.float64)[::2]
|
||||
assert_raises(ValueError, self.module.foo_sum, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.float64)
|
||||
self.module.foo_sum(x)
|
||||
assert_equal(x, [0 + 1*3*3 + 2*3*3, 1*3, 2*3])
|
@ -0,0 +1,32 @@
|
||||
"""See https://github.com/numpy/numpy/pull/10676.
|
||||
|
||||
"""
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
from numpy.testing import assert_equal
|
||||
from . import util
|
||||
|
||||
|
||||
class TestQuotedCharacter(util.F2PyTest):
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.skipif(sys.platform=='win32',
|
||||
reason='Fails with MinGW64 Gfortran (Issue #9673)')
|
||||
def test_quoted_character(self):
|
||||
assert_equal(self.module.foo(), (b"'", b'"', b';', b'!', b'(', b')'))
|
55
.venv/Lib/site-packages/numpy/f2py/tests/test_regression.py
Normal file
55
.venv/Lib/site-packages/numpy/f2py/tests/test_regression.py
Normal file
@ -0,0 +1,55 @@
|
||||
import os
|
||||
import pytest
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_, assert_raises, assert_equal, assert_string_equal
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
|
||||
class TestIntentInOut(util.F2PyTest):
|
||||
# Check that intent(in out) translates as intent(inout)
|
||||
sources = [_path('src', 'regression', 'inout.f90')]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_inout(self):
|
||||
# non-contiguous should raise error
|
||||
x = np.arange(6, dtype=np.float32)[::2]
|
||||
assert_raises(ValueError, self.module.foo, x)
|
||||
|
||||
# check values with contiguous array
|
||||
x = np.arange(3, dtype=np.float32)
|
||||
self.module.foo(x)
|
||||
assert_equal(x, [3, 1, 2])
|
||||
|
||||
|
||||
class TestNumpyVersionAttribute(util.F2PyTest):
|
||||
# Check that th attribute __f2py_numpy_version__ is present
|
||||
# in the compiled module and that has the value np.__version__.
|
||||
sources = [_path('src', 'regression', 'inout.f90')]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_numpy_version_attribute(self):
|
||||
|
||||
# Check that self.module has an attribute named "__f2py_numpy_version__"
|
||||
assert_(hasattr(self.module, "__f2py_numpy_version__"),
|
||||
msg="Fortran module does not have __f2py_numpy_version__")
|
||||
|
||||
# Check that the attribute __f2py_numpy_version__ is a string
|
||||
assert_(isinstance(self.module.__f2py_numpy_version__, str),
|
||||
msg="__f2py_numpy_version__ is not a string")
|
||||
|
||||
# Check that __f2py_numpy_version__ has the value numpy.__version__
|
||||
assert_string_equal(np.__version__, self.module.__f2py_numpy_version__)
|
||||
|
||||
|
||||
def test_include_path():
|
||||
incdir = np.f2py.get_include()
|
||||
fnames_in_dir = os.listdir(incdir)
|
||||
for fname in ('fortranobject.c', 'fortranobject.h'):
|
||||
assert fname in fnames_in_dir
|
||||
|
@ -0,0 +1,145 @@
|
||||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from numpy.testing import assert_
|
||||
from . import util
|
||||
import platform
|
||||
IS_S390X = platform.machine() == 's390x'
|
||||
|
||||
|
||||
class TestReturnCharacter(util.F2PyTest):
|
||||
|
||||
def check_function(self, t, tname):
|
||||
if tname in ['t0', 't1', 's0', 's1']:
|
||||
assert_(t(23) == b'2')
|
||||
r = t('ab')
|
||||
assert_(r == b'a', repr(r))
|
||||
r = t(array('ab'))
|
||||
assert_(r == b'a', repr(r))
|
||||
r = t(array(77, 'u1'))
|
||||
assert_(r == b'M', repr(r))
|
||||
#assert_(_raises(ValueError, t, array([77,87])))
|
||||
#assert_(_raises(ValueError, t, array(77)))
|
||||
elif tname in ['ts', 'ss']:
|
||||
assert_(t(23) == b'23', repr(t(23)))
|
||||
assert_(t('123456789abcdef') == b'123456789a')
|
||||
elif tname in ['t5', 's5']:
|
||||
assert_(t(23) == b'23', repr(t(23)))
|
||||
assert_(t('ab') == b'ab', repr(t('ab')))
|
||||
assert_(t('123456789abcdef') == b'12345')
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class TestF77ReturnCharacter(TestReturnCharacter):
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.xfail(IS_S390X, reason="callback returns ' '")
|
||||
@pytest.mark.parametrize('name', 't0,t1,t5,s0,s1,s5,ss'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module, name), name)
|
||||
|
||||
|
||||
class TestF90ReturnCharacter(TestReturnCharacter):
|
||||
suffix = ".f90"
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.xfail(IS_S390X, reason="callback returns ' '")
|
||||
@pytest.mark.parametrize('name', 't0,t1,t5,ts,s0,s1,s5,ss'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module.f90_return_char, name), name)
|
163
.venv/Lib/site-packages/numpy/f2py/tests/test_return_complex.py
Normal file
163
.venv/Lib/site-packages/numpy/f2py/tests/test_return_complex.py
Normal file
@ -0,0 +1,163 @@
|
||||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from numpy.testing import assert_, assert_raises
|
||||
from . import util
|
||||
|
||||
|
||||
class TestReturnComplex(util.F2PyTest):
|
||||
|
||||
def check_function(self, t, tname):
|
||||
if tname in ['t0', 't8', 's0', 's8']:
|
||||
err = 1e-5
|
||||
else:
|
||||
err = 0.0
|
||||
assert_(abs(t(234j) - 234.0j) <= err)
|
||||
assert_(abs(t(234.6) - 234.6) <= err)
|
||||
assert_(abs(t(234) - 234.0) <= err)
|
||||
assert_(abs(t(234.6 + 3j) - (234.6 + 3j)) <= err)
|
||||
#assert_( abs(t('234')-234.)<=err)
|
||||
#assert_( abs(t('234.6')-234.6)<=err)
|
||||
assert_(abs(t(-234) + 234.) <= err)
|
||||
assert_(abs(t([234]) - 234.) <= err)
|
||||
assert_(abs(t((234,)) - 234.) <= err)
|
||||
assert_(abs(t(array(234)) - 234.) <= err)
|
||||
assert_(abs(t(array(23 + 4j, 'F')) - (23 + 4j)) <= err)
|
||||
assert_(abs(t(array([234])) - 234.) <= err)
|
||||
assert_(abs(t(array([[234]])) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'b')) + 22.) <= err)
|
||||
assert_(abs(t(array([234], 'h')) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'i')) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'l')) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'q')) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'f')) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'd')) - 234.) <= err)
|
||||
assert_(abs(t(array([234 + 3j], 'F')) - (234 + 3j)) <= err)
|
||||
assert_(abs(t(array([234], 'D')) - 234.) <= err)
|
||||
|
||||
#assert_raises(TypeError, t, array([234], 'a1'))
|
||||
assert_raises(TypeError, t, 'abc')
|
||||
|
||||
assert_raises(IndexError, t, [])
|
||||
assert_raises(IndexError, t, ())
|
||||
|
||||
assert_raises(TypeError, t, t)
|
||||
assert_raises(TypeError, t, {})
|
||||
|
||||
try:
|
||||
r = t(10 ** 400)
|
||||
assert_(repr(r) in ['(inf+0j)', '(Infinity+0j)'], repr(r))
|
||||
except OverflowError:
|
||||
pass
|
||||
|
||||
|
||||
class TestF77ReturnComplex(TestReturnComplex):
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize('name', 't0,t8,t16,td,s0,s8,s16,sd'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module, name), name)
|
||||
|
||||
|
||||
class TestF90ReturnComplex(TestReturnComplex):
|
||||
suffix = ".f90"
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize('name', 't0,t8,t16,td,s0,s8,s16,sd'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module.f90_return_complex, name), name)
|
175
.venv/Lib/site-packages/numpy/f2py/tests/test_return_integer.py
Normal file
175
.venv/Lib/site-packages/numpy/f2py/tests/test_return_integer.py
Normal file
@ -0,0 +1,175 @@
|
||||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from numpy.testing import assert_, assert_raises
|
||||
from . import util
|
||||
|
||||
|
||||
class TestReturnInteger(util.F2PyTest):
|
||||
|
||||
def check_function(self, t, tname):
|
||||
assert_(t(123) == 123, repr(t(123)))
|
||||
assert_(t(123.6) == 123)
|
||||
assert_(t('123') == 123)
|
||||
assert_(t(-123) == -123)
|
||||
assert_(t([123]) == 123)
|
||||
assert_(t((123,)) == 123)
|
||||
assert_(t(array(123)) == 123)
|
||||
assert_(t(array([123])) == 123)
|
||||
assert_(t(array([[123]])) == 123)
|
||||
assert_(t(array([123], 'b')) == 123)
|
||||
assert_(t(array([123], 'h')) == 123)
|
||||
assert_(t(array([123], 'i')) == 123)
|
||||
assert_(t(array([123], 'l')) == 123)
|
||||
assert_(t(array([123], 'B')) == 123)
|
||||
assert_(t(array([123], 'f')) == 123)
|
||||
assert_(t(array([123], 'd')) == 123)
|
||||
|
||||
#assert_raises(ValueError, t, array([123],'S3'))
|
||||
assert_raises(ValueError, t, 'abc')
|
||||
|
||||
assert_raises(IndexError, t, [])
|
||||
assert_raises(IndexError, t, ())
|
||||
|
||||
assert_raises(Exception, t, t)
|
||||
assert_raises(Exception, t, {})
|
||||
|
||||
if tname in ['t8', 's8']:
|
||||
assert_raises(OverflowError, t, 100000000000000000000000)
|
||||
assert_raises(OverflowError, t, 10000000011111111111111.23)
|
||||
|
||||
|
||||
class TestF77ReturnInteger(TestReturnInteger):
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize('name',
|
||||
't0,t1,t2,t4,t8,s0,s1,s2,s4,s8'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module, name), name)
|
||||
|
||||
|
||||
class TestF90ReturnInteger(TestReturnInteger):
|
||||
suffix = ".f90"
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize('name',
|
||||
't0,t1,t2,t4,t8,s0,s1,s2,s4,s8'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module.f90_return_integer, name), name)
|
185
.venv/Lib/site-packages/numpy/f2py/tests/test_return_logical.py
Normal file
185
.venv/Lib/site-packages/numpy/f2py/tests/test_return_logical.py
Normal file
@ -0,0 +1,185 @@
|
||||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from numpy.testing import assert_, assert_raises
|
||||
from . import util
|
||||
|
||||
|
||||
class TestReturnLogical(util.F2PyTest):
|
||||
|
||||
def check_function(self, t):
|
||||
assert_(t(True) == 1, repr(t(True)))
|
||||
assert_(t(False) == 0, repr(t(False)))
|
||||
assert_(t(0) == 0)
|
||||
assert_(t(None) == 0)
|
||||
assert_(t(0.0) == 0)
|
||||
assert_(t(0j) == 0)
|
||||
assert_(t(1j) == 1)
|
||||
assert_(t(234) == 1)
|
||||
assert_(t(234.6) == 1)
|
||||
assert_(t(234.6 + 3j) == 1)
|
||||
assert_(t('234') == 1)
|
||||
assert_(t('aaa') == 1)
|
||||
assert_(t('') == 0)
|
||||
assert_(t([]) == 0)
|
||||
assert_(t(()) == 0)
|
||||
assert_(t({}) == 0)
|
||||
assert_(t(t) == 1)
|
||||
assert_(t(-234) == 1)
|
||||
assert_(t(10 ** 100) == 1)
|
||||
assert_(t([234]) == 1)
|
||||
assert_(t((234,)) == 1)
|
||||
assert_(t(array(234)) == 1)
|
||||
assert_(t(array([234])) == 1)
|
||||
assert_(t(array([[234]])) == 1)
|
||||
assert_(t(array([234], 'b')) == 1)
|
||||
assert_(t(array([234], 'h')) == 1)
|
||||
assert_(t(array([234], 'i')) == 1)
|
||||
assert_(t(array([234], 'l')) == 1)
|
||||
assert_(t(array([234], 'f')) == 1)
|
||||
assert_(t(array([234], 'd')) == 1)
|
||||
assert_(t(array([234 + 3j], 'F')) == 1)
|
||||
assert_(t(array([234], 'D')) == 1)
|
||||
assert_(t(array(0)) == 0)
|
||||
assert_(t(array([0])) == 0)
|
||||
assert_(t(array([[0]])) == 0)
|
||||
assert_(t(array([0j])) == 0)
|
||||
assert_(t(array([1])) == 1)
|
||||
assert_raises(ValueError, t, array([0, 0]))
|
||||
|
||||
|
||||
class TestF77ReturnLogical(TestReturnLogical):
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.slow
|
||||
@pytest.mark.parametrize('name', 't0,t1,t2,t4,s0,s1,s2,s4'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module, name))
|
||||
|
||||
|
||||
class TestF90ReturnLogical(TestReturnLogical):
|
||||
suffix = ".f90"
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.slow
|
||||
@pytest.mark.parametrize('name',
|
||||
't0,t1,t2,t4,t8,s0,s1,s2,s4,s8'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module.f90_return_logical, name))
|
203
.venv/Lib/site-packages/numpy/f2py/tests/test_return_real.py
Normal file
203
.venv/Lib/site-packages/numpy/f2py/tests/test_return_real.py
Normal file
@ -0,0 +1,203 @@
|
||||
import platform
|
||||
import pytest
|
||||
|
||||
from numpy import array
|
||||
from numpy.testing import assert_, assert_raises
|
||||
from . import util
|
||||
|
||||
|
||||
class TestReturnReal(util.F2PyTest):
|
||||
|
||||
def check_function(self, t, tname):
|
||||
if tname in ['t0', 't4', 's0', 's4']:
|
||||
err = 1e-5
|
||||
else:
|
||||
err = 0.0
|
||||
assert_(abs(t(234) - 234.0) <= err)
|
||||
assert_(abs(t(234.6) - 234.6) <= err)
|
||||
assert_(abs(t('234') - 234) <= err)
|
||||
assert_(abs(t('234.6') - 234.6) <= err)
|
||||
assert_(abs(t(-234) + 234) <= err)
|
||||
assert_(abs(t([234]) - 234) <= err)
|
||||
assert_(abs(t((234,)) - 234.) <= err)
|
||||
assert_(abs(t(array(234)) - 234.) <= err)
|
||||
assert_(abs(t(array([234])) - 234.) <= err)
|
||||
assert_(abs(t(array([[234]])) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'b')) + 22) <= err)
|
||||
assert_(abs(t(array([234], 'h')) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'i')) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'l')) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'B')) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'f')) - 234.) <= err)
|
||||
assert_(abs(t(array([234], 'd')) - 234.) <= err)
|
||||
if tname in ['t0', 't4', 's0', 's4']:
|
||||
assert_(t(1e200) == t(1e300)) # inf
|
||||
|
||||
#assert_raises(ValueError, t, array([234], 'S1'))
|
||||
assert_raises(ValueError, t, 'abc')
|
||||
|
||||
assert_raises(IndexError, t, [])
|
||||
assert_raises(IndexError, t, ())
|
||||
|
||||
assert_raises(Exception, t, t)
|
||||
assert_raises(Exception, t, {})
|
||||
|
||||
try:
|
||||
r = t(10 ** 400)
|
||||
assert_(repr(r) in ['inf', 'Infinity'], repr(r))
|
||||
except OverflowError:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
platform.system() == 'Darwin',
|
||||
reason="Prone to error when run with numpy/f2py/tests on mac os, "
|
||||
"but not when run in isolation")
|
||||
class TestCReturnReal(TestReturnReal):
|
||||
suffix = ".pyf"
|
||||
module_name = "c_ext_return_real"
|
||||
code = """
|
||||
python module c_ext_return_real
|
||||
usercode \'\'\'
|
||||
float t4(float value) { return value; }
|
||||
void s4(float *t4, float value) { *t4 = value; }
|
||||
double t8(double value) { return value; }
|
||||
void s8(double *t8, double value) { *t8 = value; }
|
||||
\'\'\'
|
||||
interface
|
||||
function t4(value)
|
||||
real*4 intent(c) :: t4,value
|
||||
end
|
||||
function t8(value)
|
||||
real*8 intent(c) :: t8,value
|
||||
end
|
||||
subroutine s4(t4,value)
|
||||
intent(c) s4
|
||||
real*4 intent(out) :: t4
|
||||
real*4 intent(c) :: value
|
||||
end
|
||||
subroutine s8(t8,value)
|
||||
intent(c) s8
|
||||
real*8 intent(out) :: t8
|
||||
real*8 intent(c) :: value
|
||||
end
|
||||
end interface
|
||||
end python module c_ext_return_real
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize('name', 't4,t8,s4,s8'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module, name), name)
|
||||
|
||||
|
||||
class TestF77ReturnReal(TestReturnReal):
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize('name', 't0,t4,t8,td,s0,s4,s8,sd'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module, name), name)
|
||||
|
||||
|
||||
class TestF90ReturnReal(TestReturnReal):
|
||||
suffix = ".f90"
|
||||
code = """
|
||||
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
|
||||
"""
|
||||
|
||||
@pytest.mark.parametrize('name', 't0,t4,t8,td,s0,s4,s8,sd'.split(','))
|
||||
def test_all(self, name):
|
||||
self.check_function(getattr(self.module.f90_return_real, name), name)
|
@ -0,0 +1,63 @@
|
||||
import platform
|
||||
import pytest
|
||||
|
||||
from . import util
|
||||
from numpy.testing import assert_equal
|
||||
|
||||
@pytest.mark.skipif(
|
||||
platform.system() == 'Darwin',
|
||||
reason="Prone to error when run with numpy/f2py/tests on mac os, "
|
||||
"but not when run in isolation")
|
||||
class TestMultiline(util.F2PyTest):
|
||||
suffix = ".pyf"
|
||||
module_name = "multiline"
|
||||
code = """
|
||||
python module {module}
|
||||
usercode '''
|
||||
void foo(int* x) {{
|
||||
char dummy = ';';
|
||||
*x = 42;
|
||||
}}
|
||||
'''
|
||||
interface
|
||||
subroutine foo(x)
|
||||
intent(c) foo
|
||||
integer intent(out) :: x
|
||||
end subroutine foo
|
||||
end interface
|
||||
end python module {module}
|
||||
""".format(module=module_name)
|
||||
|
||||
def test_multiline(self):
|
||||
assert_equal(self.module.foo(), 42)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
platform.system() == 'Darwin',
|
||||
reason="Prone to error when run with numpy/f2py/tests on mac os, "
|
||||
"but not when run in isolation")
|
||||
class TestCallstatement(util.F2PyTest):
|
||||
suffix = ".pyf"
|
||||
module_name = "callstatement"
|
||||
code = """
|
||||
python module {module}
|
||||
usercode '''
|
||||
void foo(int* x) {{
|
||||
}}
|
||||
'''
|
||||
interface
|
||||
subroutine foo(x)
|
||||
intent(c) foo
|
||||
integer intent(out) :: x
|
||||
callprotoargument int*
|
||||
callstatement {{ &
|
||||
; &
|
||||
x = 42; &
|
||||
}}
|
||||
end subroutine foo
|
||||
end interface
|
||||
end python module {module}
|
||||
""".format(module=module_name)
|
||||
|
||||
def test_callstatement(self):
|
||||
assert_equal(self.module.foo(), 42)
|
49
.venv/Lib/site-packages/numpy/f2py/tests/test_size.py
Normal file
49
.venv/Lib/site-packages/numpy/f2py/tests/test_size.py
Normal file
@ -0,0 +1,49 @@
|
||||
import os
|
||||
import pytest
|
||||
|
||||
from numpy.testing import assert_equal
|
||||
from . import util
|
||||
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
|
||||
class TestSizeSumExample(util.F2PyTest):
|
||||
sources = [_path('src', 'size', 'foo.f90')]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_all(self):
|
||||
r = self.module.foo([[]])
|
||||
assert_equal(r, [0], repr(r))
|
||||
|
||||
r = self.module.foo([[1, 2]])
|
||||
assert_equal(r, [3], repr(r))
|
||||
|
||||
r = self.module.foo([[1, 2], [3, 4]])
|
||||
assert_equal(r, [3, 7], repr(r))
|
||||
|
||||
r = self.module.foo([[1, 2], [3, 4], [5, 6]])
|
||||
assert_equal(r, [3, 7, 11], repr(r))
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_transpose(self):
|
||||
r = self.module.trans([[]])
|
||||
assert_equal(r.T, [[]], repr(r))
|
||||
|
||||
r = self.module.trans([[1, 2]])
|
||||
assert_equal(r, [[1], [2]], repr(r))
|
||||
|
||||
r = self.module.trans([[1, 2, 3], [4, 5, 6]])
|
||||
assert_equal(r, [[1, 4], [2, 5], [3, 6]], repr(r))
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_flatten(self):
|
||||
r = self.module.flatten([[]])
|
||||
assert_equal(r, [], repr(r))
|
||||
|
||||
r = self.module.flatten([[1, 2]])
|
||||
assert_equal(r, [1, 2], repr(r))
|
||||
|
||||
r = self.module.flatten([[1, 2, 3], [4, 5, 6]])
|
||||
assert_equal(r, [1, 2, 3, 4, 5, 6], repr(r))
|
166
.venv/Lib/site-packages/numpy/f2py/tests/test_string.py
Normal file
166
.venv/Lib/site-packages/numpy/f2py/tests/test_string.py
Normal file
@ -0,0 +1,166 @@
|
||||
import os
|
||||
import pytest
|
||||
import textwrap
|
||||
from numpy.testing import assert_array_equal
|
||||
import numpy as np
|
||||
from . import util
|
||||
|
||||
|
||||
def _path(*a):
|
||||
return os.path.join(*((os.path.dirname(__file__),) + a))
|
||||
|
||||
|
||||
class TestString(util.F2PyTest):
|
||||
sources = [_path('src', 'string', 'char.f90')]
|
||||
|
||||
@pytest.mark.slow
|
||||
def test_char(self):
|
||||
strings = np.array(['ab', 'cd', 'ef'], dtype='c').T
|
||||
inp, out = self.module.char_test.change_strings(strings,
|
||||
strings.shape[1])
|
||||
assert_array_equal(inp, strings)
|
||||
expected = strings.copy()
|
||||
expected[1, :] = 'AAA'
|
||||
assert_array_equal(out, expected)
|
||||
|
||||
|
||||
class TestDocStringArguments(util.F2PyTest):
|
||||
suffix = '.f'
|
||||
|
||||
code = """
|
||||
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
|
||||
PRINT*, "A=",A
|
||||
PRINT*, "B=",B
|
||||
PRINT*, "C=",C
|
||||
PRINT*, "D=",D
|
||||
PRINT*, "CHANGE A,B,C,D"
|
||||
A(1:1) = 'A'
|
||||
B(1:1) = 'B'
|
||||
C(1:1) = 'C'
|
||||
D(1:1) = 'D'
|
||||
PRINT*, "A=",A
|
||||
PRINT*, "B=",B
|
||||
PRINT*, "C=",C
|
||||
PRINT*, "D=",D
|
||||
END
|
||||
C END OF FILE STRING.F
|
||||
"""
|
||||
|
||||
def test_example(self):
|
||||
a = np.array(b'123\0\0')
|
||||
b = np.array(b'123\0\0')
|
||||
c = np.array(b'123')
|
||||
d = np.array(b'123')
|
||||
|
||||
self.module.foo(a, b, c, d)
|
||||
|
||||
assert a.tobytes() == b'123\0\0'
|
||||
assert b.tobytes() == b'B23\0\0', (b.tobytes(),)
|
||||
assert c.tobytes() == b'123'
|
||||
assert d.tobytes() == b'D23'
|
||||
|
||||
|
||||
class TestFixedString(util.F2PyTest):
|
||||
suffix = '.f90'
|
||||
|
||||
code = textwrap.dedent("""
|
||||
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
|
||||
""")
|
||||
|
||||
@staticmethod
|
||||
def _sint(s, start=0, end=None):
|
||||
"""Return the content of a string buffer as integer value.
|
||||
|
||||
For example:
|
||||
_sint('1234') -> 4321
|
||||
_sint('123A') -> 17321
|
||||
"""
|
||||
if isinstance(s, np.ndarray):
|
||||
s = s.tobytes()
|
||||
elif isinstance(s, str):
|
||||
s = s.encode()
|
||||
assert isinstance(s, bytes)
|
||||
if end is None:
|
||||
end = len(s)
|
||||
i = 0
|
||||
for j in range(start, min(end, len(s))):
|
||||
i += s[j] * 10 ** j
|
||||
return i
|
||||
|
||||
def _get_input(self, intent='in'):
|
||||
if intent in ['in']:
|
||||
yield ''
|
||||
yield '1'
|
||||
yield '1234'
|
||||
yield '12345'
|
||||
yield b''
|
||||
yield b'\0'
|
||||
yield b'1'
|
||||
yield b'\01'
|
||||
yield b'1\0'
|
||||
yield b'1234'
|
||||
yield b'12345'
|
||||
yield np.ndarray((), np.bytes_, buffer=b'') # array(b'', dtype='|S0')
|
||||
yield np.array(b'') # array(b'', dtype='|S1')
|
||||
yield np.array(b'\0')
|
||||
yield np.array(b'1')
|
||||
yield np.array(b'1\0')
|
||||
yield np.array(b'\01')
|
||||
yield np.array(b'1234')
|
||||
yield np.array(b'123\0')
|
||||
yield np.array(b'12345')
|
||||
|
||||
def test_intent_in(self):
|
||||
for s in self._get_input():
|
||||
r = self.module.test_in_bytes4(s)
|
||||
# also checks that s is not changed inplace
|
||||
expected = self._sint(s, end=4)
|
||||
assert r == expected, (s)
|
||||
|
||||
def test_intent_inout(self):
|
||||
for s in self._get_input(intent='inout'):
|
||||
rest = self._sint(s, start=4)
|
||||
r = self.module.test_inout_bytes4(s)
|
||||
expected = self._sint(s, end=4)
|
||||
assert r == expected
|
||||
|
||||
# check that the rest of input string is preserved
|
||||
assert rest == self._sint(s, start=4)
|
462
.venv/Lib/site-packages/numpy/f2py/tests/test_symbolic.py
Normal file
462
.venv/Lib/site-packages/numpy/f2py/tests/test_symbolic.py
Normal file
@ -0,0 +1,462 @@
|
||||
from numpy.testing import assert_raises
|
||||
from numpy.f2py.symbolic import (
|
||||
Expr, Op, ArithOp, Language,
|
||||
as_symbol, as_number, as_string, as_array, as_complex,
|
||||
as_terms, as_factors, eliminate_quotes, insert_quotes,
|
||||
fromstring, as_expr, as_apply,
|
||||
as_numer_denom, as_ternary, as_ref, as_deref,
|
||||
normalize, as_eq, as_ne, as_lt, as_gt, as_le, as_ge
|
||||
)
|
||||
from . import util
|
||||
|
||||
|
||||
class TestSymbolic(util.F2PyTest):
|
||||
|
||||
def test_eliminate_quotes(self):
|
||||
def worker(s):
|
||||
r, d = eliminate_quotes(s)
|
||||
s1 = insert_quotes(r, d)
|
||||
assert s1 == s
|
||||
|
||||
for kind in ['', 'mykind_']:
|
||||
worker(kind + '"1234" // "ABCD"')
|
||||
worker(kind + '"1234" // ' + kind + '"ABCD"')
|
||||
worker(kind + '"1234" // \'ABCD\'')
|
||||
worker(kind + '"1234" // ' + kind + '\'ABCD\'')
|
||||
worker(kind + '"1\\"2\'AB\'34"')
|
||||
worker('a = ' + kind + "'1\\'2\"AB\"34'")
|
||||
|
||||
def test_sanity(self):
|
||||
x = as_symbol('x')
|
||||
y = as_symbol('y')
|
||||
z = as_symbol('z')
|
||||
|
||||
assert x.op == Op.SYMBOL
|
||||
assert repr(x) == "Expr(Op.SYMBOL, 'x')"
|
||||
assert x == x
|
||||
assert x != y
|
||||
assert hash(x) is not None
|
||||
|
||||
n = as_number(123)
|
||||
m = as_number(456)
|
||||
assert n.op == Op.INTEGER
|
||||
assert repr(n) == "Expr(Op.INTEGER, (123, 4))"
|
||||
assert n == n
|
||||
assert n != m
|
||||
assert hash(n) is not None
|
||||
|
||||
fn = as_number(12.3)
|
||||
fm = as_number(45.6)
|
||||
assert fn.op == Op.REAL
|
||||
assert repr(fn) == "Expr(Op.REAL, (12.3, 4))"
|
||||
assert fn == fn
|
||||
assert fn != fm
|
||||
assert hash(fn) is not None
|
||||
|
||||
c = as_complex(1, 2)
|
||||
c2 = as_complex(3, 4)
|
||||
assert c.op == Op.COMPLEX
|
||||
assert repr(c) == ("Expr(Op.COMPLEX, (Expr(Op.INTEGER, (1, 4)),"
|
||||
" Expr(Op.INTEGER, (2, 4))))")
|
||||
assert c == c
|
||||
assert c != c2
|
||||
assert hash(c) is not None
|
||||
|
||||
s = as_string("'123'")
|
||||
s2 = as_string('"ABC"')
|
||||
assert s.op == Op.STRING
|
||||
assert repr(s) == "Expr(Op.STRING, (\"'123'\", 1))", repr(s)
|
||||
assert s == s
|
||||
assert s != s2
|
||||
|
||||
a = as_array((n, m))
|
||||
b = as_array((n,))
|
||||
assert a.op == Op.ARRAY
|
||||
assert repr(a) == ("Expr(Op.ARRAY, (Expr(Op.INTEGER, (123, 4)),"
|
||||
" Expr(Op.INTEGER, (456, 4))))")
|
||||
assert a == a
|
||||
assert a != b
|
||||
|
||||
t = as_terms(x)
|
||||
u = as_terms(y)
|
||||
assert t.op == Op.TERMS
|
||||
assert repr(t) == "Expr(Op.TERMS, {Expr(Op.SYMBOL, 'x'): 1})"
|
||||
assert t == t
|
||||
assert t != u
|
||||
assert hash(t) is not None
|
||||
|
||||
v = as_factors(x)
|
||||
w = as_factors(y)
|
||||
assert v.op == Op.FACTORS
|
||||
assert repr(v) == "Expr(Op.FACTORS, {Expr(Op.SYMBOL, 'x'): 1})"
|
||||
assert v == v
|
||||
assert w != v
|
||||
assert hash(v) is not None
|
||||
|
||||
t = as_ternary(x, y, z)
|
||||
u = as_ternary(x, z, y)
|
||||
assert t.op == Op.TERNARY
|
||||
assert t == t
|
||||
assert t != u
|
||||
assert hash(t) is not None
|
||||
|
||||
e = as_eq(x, y)
|
||||
f = as_lt(x, y)
|
||||
assert e.op == Op.RELATIONAL
|
||||
assert e == e
|
||||
assert e != f
|
||||
assert hash(e) is not None
|
||||
|
||||
def test_tostring_fortran(self):
|
||||
x = as_symbol('x')
|
||||
y = as_symbol('y')
|
||||
z = as_symbol('z')
|
||||
n = as_number(123)
|
||||
m = as_number(456)
|
||||
a = as_array((n, m))
|
||||
c = as_complex(n, m)
|
||||
|
||||
assert str(x) == 'x'
|
||||
assert str(n) == '123'
|
||||
assert str(a) == '[123, 456]'
|
||||
assert str(c) == '(123, 456)'
|
||||
|
||||
assert str(Expr(Op.TERMS, {x: 1})) == 'x'
|
||||
assert str(Expr(Op.TERMS, {x: 2})) == '2 * x'
|
||||
assert str(Expr(Op.TERMS, {x: -1})) == '-x'
|
||||
assert str(Expr(Op.TERMS, {x: -2})) == '-2 * x'
|
||||
assert str(Expr(Op.TERMS, {x: 1, y: 1})) == 'x + y'
|
||||
assert str(Expr(Op.TERMS, {x: -1, y: -1})) == '-x - y'
|
||||
assert str(Expr(Op.TERMS, {x: 2, y: 3})) == '2 * x + 3 * y'
|
||||
assert str(Expr(Op.TERMS, {x: -2, y: 3})) == '-2 * x + 3 * y'
|
||||
assert str(Expr(Op.TERMS, {x: 2, y: -3})) == '2 * x - 3 * y'
|
||||
|
||||
assert str(Expr(Op.FACTORS, {x: 1})) == 'x'
|
||||
assert str(Expr(Op.FACTORS, {x: 2})) == 'x ** 2'
|
||||
assert str(Expr(Op.FACTORS, {x: -1})) == 'x ** -1'
|
||||
assert str(Expr(Op.FACTORS, {x: -2})) == 'x ** -2'
|
||||
assert str(Expr(Op.FACTORS, {x: 1, y: 1})) == 'x * y'
|
||||
assert str(Expr(Op.FACTORS, {x: 2, y: 3})) == 'x ** 2 * y ** 3'
|
||||
|
||||
v = Expr(Op.FACTORS, {x: 2, Expr(Op.TERMS, {x: 1, y: 1}): 3})
|
||||
assert str(v) == 'x ** 2 * (x + y) ** 3', str(v)
|
||||
v = Expr(Op.FACTORS, {x: 2, Expr(Op.FACTORS, {x: 1, y: 1}): 3})
|
||||
assert str(v) == 'x ** 2 * (x * y) ** 3', str(v)
|
||||
|
||||
assert str(Expr(Op.APPLY, ('f', (), {}))) == 'f()'
|
||||
assert str(Expr(Op.APPLY, ('f', (x,), {}))) == 'f(x)'
|
||||
assert str(Expr(Op.APPLY, ('f', (x, y), {}))) == 'f(x, y)'
|
||||
assert str(Expr(Op.INDEXING, ('f', x))) == 'f[x]'
|
||||
|
||||
assert str(as_ternary(x, y, z)) == 'merge(y, z, x)'
|
||||
assert str(as_eq(x, y)) == 'x .eq. y'
|
||||
assert str(as_ne(x, y)) == 'x .ne. y'
|
||||
assert str(as_lt(x, y)) == 'x .lt. y'
|
||||
assert str(as_le(x, y)) == 'x .le. y'
|
||||
assert str(as_gt(x, y)) == 'x .gt. y'
|
||||
assert str(as_ge(x, y)) == 'x .ge. y'
|
||||
|
||||
def test_tostring_c(self):
|
||||
language = Language.C
|
||||
x = as_symbol('x')
|
||||
y = as_symbol('y')
|
||||
z = as_symbol('z')
|
||||
n = as_number(123)
|
||||
|
||||
assert Expr(Op.FACTORS, {x: 2}).tostring(language=language) == 'x * x'
|
||||
assert Expr(Op.FACTORS, {x + y: 2}).tostring(
|
||||
language=language) == '(x + y) * (x + y)'
|
||||
assert Expr(Op.FACTORS, {x: 12}).tostring(
|
||||
language=language) == 'pow(x, 12)'
|
||||
|
||||
assert as_apply(ArithOp.DIV, x, y).tostring(
|
||||
language=language) == 'x / y'
|
||||
assert as_apply(ArithOp.DIV, x, x + y).tostring(
|
||||
language=language) == 'x / (x + y)'
|
||||
assert as_apply(ArithOp.DIV, x - y, x + y).tostring(
|
||||
language=language) == '(x - y) / (x + y)'
|
||||
assert (x + (x - y) / (x + y) + n).tostring(
|
||||
language=language) == '123 + x + (x - y) / (x + y)'
|
||||
|
||||
assert as_ternary(x, y, z).tostring(language=language) == "(x?y:z)"
|
||||
assert as_eq(x, y).tostring(language=language) == "x == y"
|
||||
assert as_ne(x, y).tostring(language=language) == "x != y"
|
||||
assert as_lt(x, y).tostring(language=language) == "x < y"
|
||||
assert as_le(x, y).tostring(language=language) == "x <= y"
|
||||
assert as_gt(x, y).tostring(language=language) == "x > y"
|
||||
assert as_ge(x, y).tostring(language=language) == "x >= y"
|
||||
|
||||
def test_operations(self):
|
||||
x = as_symbol('x')
|
||||
y = as_symbol('y')
|
||||
z = as_symbol('z')
|
||||
|
||||
assert x + x == Expr(Op.TERMS, {x: 2})
|
||||
assert x - x == Expr(Op.INTEGER, (0, 4))
|
||||
assert x + y == Expr(Op.TERMS, {x: 1, y: 1})
|
||||
assert x - y == Expr(Op.TERMS, {x: 1, y: -1})
|
||||
assert x * x == Expr(Op.FACTORS, {x: 2})
|
||||
assert x * y == Expr(Op.FACTORS, {x: 1, y: 1})
|
||||
|
||||
assert +x == x
|
||||
assert -x == Expr(Op.TERMS, {x: -1}), repr(-x)
|
||||
assert 2 * x == Expr(Op.TERMS, {x: 2})
|
||||
assert 2 + x == Expr(Op.TERMS, {x: 1, as_number(1): 2})
|
||||
assert 2 * x + 3 * y == Expr(Op.TERMS, {x: 2, y: 3})
|
||||
assert (x + y) * 2 == Expr(Op.TERMS, {x: 2, y: 2})
|
||||
|
||||
assert x ** 2 == Expr(Op.FACTORS, {x: 2})
|
||||
assert (x + y) ** 2 == Expr(Op.TERMS,
|
||||
{Expr(Op.FACTORS, {x: 2}): 1,
|
||||
Expr(Op.FACTORS, {y: 2}): 1,
|
||||
Expr(Op.FACTORS, {x: 1, y: 1}): 2})
|
||||
assert (x + y) * x == x ** 2 + x * y
|
||||
assert (x + y) ** 2 == x ** 2 + 2 * x * y + y ** 2
|
||||
assert (x + y) ** 2 + (x - y) ** 2 == 2 * x ** 2 + 2 * y ** 2
|
||||
assert (x + y) * z == x * z + y * z
|
||||
assert z * (x + y) == x * z + y * z
|
||||
|
||||
assert (x / 2) == as_apply(ArithOp.DIV, x, as_number(2))
|
||||
assert (2 * x / 2) == x
|
||||
assert (3 * x / 2) == as_apply(ArithOp.DIV, 3*x, as_number(2))
|
||||
assert (4 * x / 2) == 2 * x
|
||||
assert (5 * x / 2) == as_apply(ArithOp.DIV, 5*x, as_number(2))
|
||||
assert (6 * x / 2) == 3 * x
|
||||
assert ((3*5) * x / 6) == as_apply(ArithOp.DIV, 5*x, as_number(2))
|
||||
assert (30*x**2*y**4 / (24*x**3*y**3)) == as_apply(ArithOp.DIV,
|
||||
5*y, 4*x)
|
||||
assert ((15 * x / 6) / 5) == as_apply(
|
||||
ArithOp.DIV, x, as_number(2)), ((15 * x / 6) / 5)
|
||||
assert (x / (5 / x)) == as_apply(ArithOp.DIV, x**2, as_number(5))
|
||||
|
||||
assert (x / 2.0) == Expr(Op.TERMS, {x: 0.5})
|
||||
|
||||
s = as_string('"ABC"')
|
||||
t = as_string('"123"')
|
||||
|
||||
assert s // t == Expr(Op.STRING, ('"ABC123"', 1))
|
||||
assert s // x == Expr(Op.CONCAT, (s, x))
|
||||
assert x // s == Expr(Op.CONCAT, (x, s))
|
||||
|
||||
c = as_complex(1., 2.)
|
||||
assert -c == as_complex(-1., -2.)
|
||||
assert c + c == as_expr((1+2j)*2)
|
||||
assert c * c == as_expr((1+2j)**2)
|
||||
|
||||
def test_substitute(self):
|
||||
x = as_symbol('x')
|
||||
y = as_symbol('y')
|
||||
z = as_symbol('z')
|
||||
a = as_array((x, y))
|
||||
|
||||
assert x.substitute({x: y}) == y
|
||||
assert (x + y).substitute({x: z}) == y + z
|
||||
assert (x * y).substitute({x: z}) == y * z
|
||||
assert (x ** 4).substitute({x: z}) == z ** 4
|
||||
assert (x / y).substitute({x: z}) == z / y
|
||||
assert x.substitute({x: y + z}) == y + z
|
||||
assert a.substitute({x: y + z}) == as_array((y + z, y))
|
||||
|
||||
assert as_ternary(x, y, z).substitute(
|
||||
{x: y + z}) == as_ternary(y + z, y, z)
|
||||
assert as_eq(x, y).substitute(
|
||||
{x: y + z}) == as_eq(y + z, y)
|
||||
|
||||
def test_fromstring(self):
|
||||
|
||||
x = as_symbol('x')
|
||||
y = as_symbol('y')
|
||||
z = as_symbol('z')
|
||||
f = as_symbol('f')
|
||||
s = as_string('"ABC"')
|
||||
t = as_string('"123"')
|
||||
a = as_array((x, y))
|
||||
|
||||
assert fromstring('x') == x
|
||||
assert fromstring('+ x') == x
|
||||
assert fromstring('- x') == -x
|
||||
assert fromstring('x + y') == x + y
|
||||
assert fromstring('x + 1') == x + 1
|
||||
assert fromstring('x * y') == x * y
|
||||
assert fromstring('x * 2') == x * 2
|
||||
assert fromstring('x / y') == x / y
|
||||
assert fromstring('x ** 2',
|
||||
language=Language.Python) == x ** 2
|
||||
assert fromstring('x ** 2 ** 3',
|
||||
language=Language.Python) == x ** 2 ** 3
|
||||
assert fromstring('(x + y) * z') == (x + y) * z
|
||||
|
||||
assert fromstring('f(x)') == f(x)
|
||||
assert fromstring('f(x,y)') == f(x, y)
|
||||
assert fromstring('f[x]') == f[x]
|
||||
assert fromstring('f[x][y]') == f[x][y]
|
||||
|
||||
assert fromstring('"ABC"') == s
|
||||
assert normalize(fromstring('"ABC" // "123" ',
|
||||
language=Language.Fortran)) == s // t
|
||||
assert fromstring('f("ABC")') == f(s)
|
||||
assert fromstring('MYSTRKIND_"ABC"') == as_string('"ABC"', 'MYSTRKIND')
|
||||
|
||||
assert fromstring('(/x, y/)') == a, fromstring('(/x, y/)')
|
||||
assert fromstring('f((/x, y/))') == f(a)
|
||||
assert fromstring('(/(x+y)*z/)') == as_array(((x+y)*z,))
|
||||
|
||||
assert fromstring('123') == as_number(123)
|
||||
assert fromstring('123_2') == as_number(123, 2)
|
||||
assert fromstring('123_myintkind') == as_number(123, 'myintkind')
|
||||
|
||||
assert fromstring('123.0') == as_number(123.0, 4)
|
||||
assert fromstring('123.0_4') == as_number(123.0, 4)
|
||||
assert fromstring('123.0_8') == as_number(123.0, 8)
|
||||
assert fromstring('123.0e0') == as_number(123.0, 4)
|
||||
assert fromstring('123.0d0') == as_number(123.0, 8)
|
||||
assert fromstring('123d0') == as_number(123.0, 8)
|
||||
assert fromstring('123e-0') == as_number(123.0, 4)
|
||||
assert fromstring('123d+0') == as_number(123.0, 8)
|
||||
assert fromstring('123.0_myrealkind') == as_number(123.0, 'myrealkind')
|
||||
assert fromstring('3E4') == as_number(30000.0, 4)
|
||||
|
||||
assert fromstring('(1, 2)') == as_complex(1, 2)
|
||||
assert fromstring('(1e2, PI)') == as_complex(
|
||||
as_number(100.0), as_symbol('PI'))
|
||||
|
||||
assert fromstring('[1, 2]') == as_array((as_number(1), as_number(2)))
|
||||
|
||||
assert fromstring('POINT(x, y=1)') == as_apply(
|
||||
as_symbol('POINT'), x, y=as_number(1))
|
||||
assert (fromstring('PERSON(name="John", age=50, shape=(/34, 23/))')
|
||||
== as_apply(as_symbol('PERSON'),
|
||||
name=as_string('"John"'),
|
||||
age=as_number(50),
|
||||
shape=as_array((as_number(34), as_number(23)))))
|
||||
|
||||
assert fromstring('x?y:z') == as_ternary(x, y, z)
|
||||
|
||||
assert fromstring('*x') == as_deref(x)
|
||||
assert fromstring('**x') == as_deref(as_deref(x))
|
||||
assert fromstring('&x') == as_ref(x)
|
||||
assert fromstring('(*x) * (*y)') == as_deref(x) * as_deref(y)
|
||||
assert fromstring('(*x) * *y') == as_deref(x) * as_deref(y)
|
||||
assert fromstring('*x * *y') == as_deref(x) * as_deref(y)
|
||||
assert fromstring('*x**y') == as_deref(x) * as_deref(y)
|
||||
|
||||
assert fromstring('x == y') == as_eq(x, y)
|
||||
assert fromstring('x != y') == as_ne(x, y)
|
||||
assert fromstring('x < y') == as_lt(x, y)
|
||||
assert fromstring('x > y') == as_gt(x, y)
|
||||
assert fromstring('x <= y') == as_le(x, y)
|
||||
assert fromstring('x >= y') == as_ge(x, y)
|
||||
|
||||
assert fromstring('x .eq. y', language=Language.Fortran) == as_eq(x, y)
|
||||
assert fromstring('x .ne. y', language=Language.Fortran) == as_ne(x, y)
|
||||
assert fromstring('x .lt. y', language=Language.Fortran) == as_lt(x, y)
|
||||
assert fromstring('x .gt. y', language=Language.Fortran) == as_gt(x, y)
|
||||
assert fromstring('x .le. y', language=Language.Fortran) == as_le(x, y)
|
||||
assert fromstring('x .ge. y', language=Language.Fortran) == as_ge(x, y)
|
||||
|
||||
def test_traverse(self):
|
||||
x = as_symbol('x')
|
||||
y = as_symbol('y')
|
||||
z = as_symbol('z')
|
||||
f = as_symbol('f')
|
||||
|
||||
# Use traverse to substitute a symbol
|
||||
def replace_visit(s, r=z):
|
||||
if s == x:
|
||||
return r
|
||||
|
||||
assert x.traverse(replace_visit) == z
|
||||
assert y.traverse(replace_visit) == y
|
||||
assert z.traverse(replace_visit) == z
|
||||
assert (f(y)).traverse(replace_visit) == f(y)
|
||||
assert (f(x)).traverse(replace_visit) == f(z)
|
||||
assert (f[y]).traverse(replace_visit) == f[y]
|
||||
assert (f[z]).traverse(replace_visit) == f[z]
|
||||
assert (x + y + z).traverse(replace_visit) == (2 * z + y)
|
||||
assert (x + f(y, x - z)).traverse(
|
||||
replace_visit) == (z + f(y, as_number(0)))
|
||||
assert as_eq(x, y).traverse(replace_visit) == as_eq(z, y)
|
||||
|
||||
# Use traverse to collect symbols, method 1
|
||||
function_symbols = set()
|
||||
symbols = set()
|
||||
|
||||
def collect_symbols(s):
|
||||
if s.op is Op.APPLY:
|
||||
oper = s.data[0]
|
||||
function_symbols.add(oper)
|
||||
if oper in symbols:
|
||||
symbols.remove(oper)
|
||||
elif s.op is Op.SYMBOL and s not in function_symbols:
|
||||
symbols.add(s)
|
||||
|
||||
(x + f(y, x - z)).traverse(collect_symbols)
|
||||
assert function_symbols == {f}
|
||||
assert symbols == {x, y, z}
|
||||
|
||||
# Use traverse to collect symbols, method 2
|
||||
def collect_symbols2(expr, symbols):
|
||||
if expr.op is Op.SYMBOL:
|
||||
symbols.add(expr)
|
||||
|
||||
symbols = set()
|
||||
(x + f(y, x - z)).traverse(collect_symbols2, symbols)
|
||||
assert symbols == {x, y, z, f}
|
||||
|
||||
# Use traverse to partially collect symbols
|
||||
def collect_symbols3(expr, symbols):
|
||||
if expr.op is Op.APPLY:
|
||||
# skip traversing function calls
|
||||
return expr
|
||||
if expr.op is Op.SYMBOL:
|
||||
symbols.add(expr)
|
||||
|
||||
symbols = set()
|
||||
(x + f(y, x - z)).traverse(collect_symbols3, symbols)
|
||||
assert symbols == {x}
|
||||
|
||||
def test_linear_solve(self):
|
||||
x = as_symbol('x')
|
||||
y = as_symbol('y')
|
||||
z = as_symbol('z')
|
||||
|
||||
assert x.linear_solve(x) == (as_number(1), as_number(0))
|
||||
assert (x+1).linear_solve(x) == (as_number(1), as_number(1))
|
||||
assert (2*x).linear_solve(x) == (as_number(2), as_number(0))
|
||||
assert (2*x+3).linear_solve(x) == (as_number(2), as_number(3))
|
||||
assert as_number(3).linear_solve(x) == (as_number(0), as_number(3))
|
||||
assert y.linear_solve(x) == (as_number(0), y)
|
||||
assert (y*z).linear_solve(x) == (as_number(0), y * z)
|
||||
|
||||
assert (x+y).linear_solve(x) == (as_number(1), y)
|
||||
assert (z*x+y).linear_solve(x) == (z, y)
|
||||
assert ((z+y)*x+y).linear_solve(x) == (z + y, y)
|
||||
assert (z*y*x+y).linear_solve(x) == (z * y, y)
|
||||
|
||||
assert_raises(RuntimeError, lambda: (x*x).linear_solve(x))
|
||||
|
||||
def test_as_numer_denom(self):
|
||||
x = as_symbol('x')
|
||||
y = as_symbol('y')
|
||||
n = as_number(123)
|
||||
|
||||
assert as_numer_denom(x) == (x, as_number(1))
|
||||
assert as_numer_denom(x / n) == (x, n)
|
||||
assert as_numer_denom(n / x) == (n, x)
|
||||
assert as_numer_denom(x / y) == (x, y)
|
||||
assert as_numer_denom(x * y) == (x * y, as_number(1))
|
||||
assert as_numer_denom(n + x / y) == (x + n * y, y)
|
||||
assert as_numer_denom(n + x / (y - x / n)) == (y * n ** 2, y * n - x)
|
||||
|
||||
def test_polynomial_atoms(self):
|
||||
x = as_symbol('x')
|
||||
y = as_symbol('y')
|
||||
n = as_number(123)
|
||||
|
||||
assert x.polynomial_atoms() == {x}
|
||||
assert n.polynomial_atoms() == set()
|
||||
assert (y[x]).polynomial_atoms() == {y[x]}
|
||||
assert (y(x)).polynomial_atoms() == {y(x)}
|
||||
assert (y(x) + x).polynomial_atoms() == {y(x), x}
|
||||
assert (y(x) * x[y]).polynomial_atoms() == {y(x), x[y]}
|
||||
assert (y(x) ** x).polynomial_atoms() == {y(x)}
|
356
.venv/Lib/site-packages/numpy/f2py/tests/util.py
Normal file
356
.venv/Lib/site-packages/numpy/f2py/tests/util.py
Normal file
@ -0,0 +1,356 @@
|
||||
"""
|
||||
Utility functions for
|
||||
|
||||
- building and importing modules on test time, using a temporary location
|
||||
- detecting if compilers are present
|
||||
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import tempfile
|
||||
import shutil
|
||||
import atexit
|
||||
import textwrap
|
||||
import re
|
||||
import pytest
|
||||
|
||||
from numpy.compat import asbytes, asstr
|
||||
from numpy.testing import temppath
|
||||
from importlib import import_module
|
||||
|
||||
#
|
||||
# Maintaining a temporary module directory
|
||||
#
|
||||
|
||||
_module_dir = None
|
||||
_module_num = 5403
|
||||
|
||||
|
||||
def _cleanup():
|
||||
global _module_dir
|
||||
if _module_dir is not None:
|
||||
try:
|
||||
sys.path.remove(_module_dir)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
shutil.rmtree(_module_dir)
|
||||
except OSError:
|
||||
pass
|
||||
_module_dir = None
|
||||
|
||||
|
||||
def get_module_dir():
|
||||
global _module_dir
|
||||
if _module_dir is None:
|
||||
_module_dir = tempfile.mkdtemp()
|
||||
atexit.register(_cleanup)
|
||||
if _module_dir not in sys.path:
|
||||
sys.path.insert(0, _module_dir)
|
||||
return _module_dir
|
||||
|
||||
|
||||
def get_temp_module_name():
|
||||
# Assume single-threaded, and the module dir usable only by this thread
|
||||
global _module_num
|
||||
d = get_module_dir()
|
||||
name = "_test_ext_module_%d" % _module_num
|
||||
_module_num += 1
|
||||
if name in sys.modules:
|
||||
# this should not be possible, but check anyway
|
||||
raise RuntimeError("Temporary module name already in use.")
|
||||
return name
|
||||
|
||||
|
||||
def _memoize(func):
|
||||
memo = {}
|
||||
|
||||
def wrapper(*a, **kw):
|
||||
key = repr((a, kw))
|
||||
if key not in memo:
|
||||
try:
|
||||
memo[key] = func(*a, **kw)
|
||||
except Exception as e:
|
||||
memo[key] = e
|
||||
raise
|
||||
ret = memo[key]
|
||||
if isinstance(ret, Exception):
|
||||
raise ret
|
||||
return ret
|
||||
wrapper.__name__ = func.__name__
|
||||
return wrapper
|
||||
|
||||
#
|
||||
# Building modules
|
||||
#
|
||||
|
||||
|
||||
@_memoize
|
||||
def build_module(source_files, options=[], skip=[], only=[], module_name=None):
|
||||
"""
|
||||
Compile and import a f2py module, built from the given files.
|
||||
|
||||
"""
|
||||
|
||||
code = ("import sys; sys.path = %s; import numpy.f2py as f2py2e; "
|
||||
"f2py2e.main()" % repr(sys.path))
|
||||
|
||||
d = get_module_dir()
|
||||
|
||||
# Copy files
|
||||
dst_sources = []
|
||||
f2py_sources = []
|
||||
for fn in source_files:
|
||||
if not os.path.isfile(fn):
|
||||
raise RuntimeError("%s is not a file" % fn)
|
||||
dst = os.path.join(d, os.path.basename(fn))
|
||||
shutil.copyfile(fn, dst)
|
||||
dst_sources.append(dst)
|
||||
|
||||
base, ext = os.path.splitext(dst)
|
||||
if ext in ('.f90', '.f', '.c', '.pyf'):
|
||||
f2py_sources.append(dst)
|
||||
|
||||
# Prepare options
|
||||
if module_name is None:
|
||||
module_name = get_temp_module_name()
|
||||
f2py_opts = ['-c', '-m', module_name] + options + f2py_sources
|
||||
if skip:
|
||||
f2py_opts += ['skip:'] + skip
|
||||
if only:
|
||||
f2py_opts += ['only:'] + only
|
||||
|
||||
# Build
|
||||
cwd = os.getcwd()
|
||||
try:
|
||||
os.chdir(d)
|
||||
cmd = [sys.executable, '-c', code] + f2py_opts
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
out, err = p.communicate()
|
||||
if p.returncode != 0:
|
||||
raise RuntimeError("Running f2py failed: %s\n%s"
|
||||
% (cmd[4:], asstr(out)))
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
# Partial cleanup
|
||||
for fn in dst_sources:
|
||||
os.unlink(fn)
|
||||
|
||||
# Import
|
||||
return import_module(module_name)
|
||||
|
||||
|
||||
@_memoize
|
||||
def build_code(source_code, options=[], skip=[], only=[], suffix=None,
|
||||
module_name=None):
|
||||
"""
|
||||
Compile and import Fortran code using f2py.
|
||||
|
||||
"""
|
||||
if suffix is None:
|
||||
suffix = '.f'
|
||||
with temppath(suffix=suffix) as path:
|
||||
with open(path, 'w') as f:
|
||||
f.write(source_code)
|
||||
return build_module([path], options=options, skip=skip, only=only,
|
||||
module_name=module_name)
|
||||
|
||||
#
|
||||
# Check if compilers are available at all...
|
||||
#
|
||||
|
||||
_compiler_status = None
|
||||
|
||||
|
||||
def _get_compiler_status():
|
||||
global _compiler_status
|
||||
if _compiler_status is not None:
|
||||
return _compiler_status
|
||||
|
||||
_compiler_status = (False, False, False)
|
||||
|
||||
# XXX: this is really ugly. But I don't know how to invoke Distutils
|
||||
# in a safer way...
|
||||
code = textwrap.dedent("""\
|
||||
import os
|
||||
import sys
|
||||
sys.path = %(syspath)s
|
||||
|
||||
def configuration(parent_name='',top_path=None):
|
||||
global config
|
||||
from numpy.distutils.misc_util import Configuration
|
||||
config = Configuration('', parent_name, top_path)
|
||||
return config
|
||||
|
||||
from numpy.distutils.core import setup
|
||||
setup(configuration=configuration)
|
||||
|
||||
config_cmd = config.get_config_cmd()
|
||||
have_c = config_cmd.try_compile('void foo() {}')
|
||||
print('COMPILERS:%%d,%%d,%%d' %% (have_c,
|
||||
config.have_f77c(),
|
||||
config.have_f90c()))
|
||||
sys.exit(99)
|
||||
""")
|
||||
code = code % dict(syspath=repr(sys.path))
|
||||
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
try:
|
||||
script = os.path.join(tmpdir, 'setup.py')
|
||||
|
||||
with open(script, 'w') as f:
|
||||
f.write(code)
|
||||
|
||||
cmd = [sys.executable, 'setup.py', 'config']
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
cwd=tmpdir)
|
||||
out, err = p.communicate()
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
|
||||
m = re.search(br'COMPILERS:(\d+),(\d+),(\d+)', out)
|
||||
if m:
|
||||
_compiler_status = (bool(int(m.group(1))), bool(int(m.group(2))),
|
||||
bool(int(m.group(3))))
|
||||
# Finished
|
||||
return _compiler_status
|
||||
|
||||
|
||||
def has_c_compiler():
|
||||
return _get_compiler_status()[0]
|
||||
|
||||
|
||||
def has_f77_compiler():
|
||||
return _get_compiler_status()[1]
|
||||
|
||||
|
||||
def has_f90_compiler():
|
||||
return _get_compiler_status()[2]
|
||||
|
||||
#
|
||||
# Building with distutils
|
||||
#
|
||||
|
||||
|
||||
@_memoize
|
||||
def build_module_distutils(source_files, config_code, module_name, **kw):
|
||||
"""
|
||||
Build a module via distutils and import it.
|
||||
|
||||
"""
|
||||
d = get_module_dir()
|
||||
|
||||
# Copy files
|
||||
dst_sources = []
|
||||
for fn in source_files:
|
||||
if not os.path.isfile(fn):
|
||||
raise RuntimeError("%s is not a file" % fn)
|
||||
dst = os.path.join(d, os.path.basename(fn))
|
||||
shutil.copyfile(fn, dst)
|
||||
dst_sources.append(dst)
|
||||
|
||||
# Build script
|
||||
config_code = textwrap.dedent(config_code).replace("\n", "\n ")
|
||||
|
||||
code = textwrap.dedent("""\
|
||||
import os
|
||||
import sys
|
||||
sys.path = %(syspath)s
|
||||
|
||||
def configuration(parent_name='',top_path=None):
|
||||
from numpy.distutils.misc_util import Configuration
|
||||
config = Configuration('', parent_name, top_path)
|
||||
%(config_code)s
|
||||
return config
|
||||
|
||||
if __name__ == "__main__":
|
||||
from numpy.distutils.core import setup
|
||||
setup(configuration=configuration)
|
||||
""") % dict(config_code=config_code, syspath=repr(sys.path))
|
||||
|
||||
script = os.path.join(d, get_temp_module_name() + '.py')
|
||||
dst_sources.append(script)
|
||||
with open(script, 'wb') as f:
|
||||
f.write(asbytes(code))
|
||||
|
||||
# Build
|
||||
cwd = os.getcwd()
|
||||
try:
|
||||
os.chdir(d)
|
||||
cmd = [sys.executable, script, 'build_ext', '-i']
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
out, err = p.communicate()
|
||||
if p.returncode != 0:
|
||||
raise RuntimeError("Running distutils build failed: %s\n%s"
|
||||
% (cmd[4:], asstr(out)))
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
|
||||
# Partial cleanup
|
||||
for fn in dst_sources:
|
||||
os.unlink(fn)
|
||||
|
||||
# Import
|
||||
__import__(module_name)
|
||||
return sys.modules[module_name]
|
||||
|
||||
#
|
||||
# Unittest convenience
|
||||
#
|
||||
|
||||
|
||||
class F2PyTest:
|
||||
code = None
|
||||
sources = None
|
||||
options = []
|
||||
skip = []
|
||||
only = []
|
||||
suffix = '.f'
|
||||
module = None
|
||||
module_name = None
|
||||
|
||||
def setup(self):
|
||||
if sys.platform == 'win32':
|
||||
pytest.skip('Fails with MinGW64 Gfortran (Issue #9673)')
|
||||
|
||||
if self.module is not None:
|
||||
return
|
||||
|
||||
# Check compiler availability first
|
||||
if not has_c_compiler():
|
||||
pytest.skip("No C compiler available")
|
||||
|
||||
codes = []
|
||||
if self.sources:
|
||||
codes.extend(self.sources)
|
||||
if self.code is not None:
|
||||
codes.append(self.suffix)
|
||||
|
||||
needs_f77 = False
|
||||
needs_f90 = False
|
||||
for fn in codes:
|
||||
if fn.endswith('.f'):
|
||||
needs_f77 = True
|
||||
elif fn.endswith('.f90'):
|
||||
needs_f90 = True
|
||||
if needs_f77 and not has_f77_compiler():
|
||||
pytest.skip("No Fortran 77 compiler available")
|
||||
if needs_f90 and not has_f90_compiler():
|
||||
pytest.skip("No Fortran 90 compiler available")
|
||||
|
||||
# Build the module
|
||||
if self.code is not None:
|
||||
self.module = build_code(self.code, options=self.options,
|
||||
skip=self.skip, only=self.only,
|
||||
suffix=self.suffix,
|
||||
module_name=self.module_name)
|
||||
|
||||
if self.sources is not None:
|
||||
self.module = build_module(self.sources, options=self.options,
|
||||
skip=self.skip, only=self.only,
|
||||
module_name=self.module_name)
|
Reference in New Issue
Block a user