summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Papior <nickpapior@gmail.com>2016-11-23 09:11:52 +0100
committerNick Papior <nickpapior@gmail.com>2016-11-27 21:10:04 +0100
commit8a7e7a44c194e3c748ccee0862f4ae01e371a208 (patch)
tree45eaa09569e3fd84f1d9899cd8de476344b561ba
parentce6d3ffc991c63c1a91fd806b4eb3d0008caace2 (diff)
downloadnumpy-8a7e7a44c194e3c748ccee0862f4ae01e371a208.tar.gz
BUG: fixed kind specifications for parameters
Fortran sources with parameters having kind-specifiers where not correctly intercepted in the crackfortran.py source. The reason was a restrictive check for only integer specifiers which did not split real's into the correct number. Furthermore, several tests has been added which tests the different kind specifiers and their use in codes, also all of them together. Signed-off-by: Nick Papior <nickpapior@gmail.com>
-rwxr-xr-xnumpy/f2py/crackfortran.py35
-rw-r--r--numpy/f2py/tests/src/parameter/constant_both.f9057
-rw-r--r--numpy/f2py/tests/src/parameter/constant_integer.f9022
-rw-r--r--numpy/f2py/tests/src/parameter/constant_real.f9023
-rw-r--r--numpy/f2py/tests/test_parameter.py102
-rw-r--r--numpy/f2py/tests/test_regression.py5
6 files changed, 238 insertions, 6 deletions
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py
index a51eb5d38..dd772396e 100755
--- a/numpy/f2py/crackfortran.py
+++ b/numpy/f2py/crackfortran.py
@@ -2433,18 +2433,47 @@ def get_parameters(vars, global_params={}):
v = v.replace(*repl)
v = kind_re.sub(r'kind("\1")', v)
v = selected_int_kind_re.sub(r'selected_int_kind(\1)', v)
- if isinteger(vars[n]) and not selected_kind_re.match(v):
- v = v.split('_')[0]
+
+ # We need to act according to the data.
+ # The easy case is if the data has a kind-specifier,
+ # then we may easily remove those specifiers.
+ # However, it may be that the user uses other specifiers...(!)
+ is_replaced = False
+ if 'kindselector' in vars[n]:
+ if 'kind' in vars[n]['kindselector']:
+ orig_v_len = len(v)
+ v = v.replace('_' + vars[n]['kindselector']['kind'], '')
+ # Again, this will be true if even a single specifier
+ # has been replaced, see comment above.
+ is_replaced = len(v) < orig_v_len
+
+ if not is_replaced:
+ if not selected_kind_re.match(v):
+ v_ = v.split('_')
+ # In case there are additive parameters
+ v = ''.join(v_[:-1]).lower().replace(v_[-1].lower(), '')
+
+ # Currently this will not work for complex numbers.
+ # There is missing code for extracting a complex number,
+ # which may be defined in either of these:
+ # a) (Re, Im)
+ # b) cmplx(Re, Im)
+ # c) dcmplx(Re, Im)
+ # d) cmplx(Re, Im, <prec>)
+
if isdouble(vars[n]):
tt = list(v)
for m in real16pattern.finditer(v):
tt[m.start():m.end()] = list(
v[m.start():m.end()].lower().replace('d', 'e'))
v = ''.join(tt)
- if iscomplex(vars[n]):
+
+ elif iscomplex(vars[n]):
+ # FIXME complex numbers may also have exponents
if v[0] == '(' and v[-1] == ')':
# FIXME, unused l looks like potential bug
l = markoutercomma(v[1:-1]).split('@,@')
+
try:
params[n] = eval(v, g_params, params)
except Exception as msg:
diff --git a/numpy/f2py/tests/src/parameter/constant_both.f90 b/numpy/f2py/tests/src/parameter/constant_both.f90
new file mode 100644
index 000000000..ac90cedc5
--- /dev/null
+++ b/numpy/f2py/tests/src/parameter/constant_both.f90
@@ -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
diff --git a/numpy/f2py/tests/src/parameter/constant_integer.f90 b/numpy/f2py/tests/src/parameter/constant_integer.f90
new file mode 100644
index 000000000..aaa83d2eb
--- /dev/null
+++ b/numpy/f2py/tests/src/parameter/constant_integer.f90
@@ -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
diff --git a/numpy/f2py/tests/src/parameter/constant_real.f90 b/numpy/f2py/tests/src/parameter/constant_real.f90
new file mode 100644
index 000000000..02ac9dd99
--- /dev/null
+++ b/numpy/f2py/tests/src/parameter/constant_real.f90
@@ -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
+
diff --git a/numpy/f2py/tests/test_parameter.py b/numpy/f2py/tests/test_parameter.py
new file mode 100644
index 000000000..f0168b2d5
--- /dev/null
+++ b/numpy/f2py/tests/test_parameter.py
@@ -0,0 +1,102 @@
+from __future__ import division, absolute_import, print_function
+
+import os
+import math
+
+import numpy as np
+from numpy.testing import run_module_suite, dec, assert_raises, assert_equal
+
+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'),
+ ]
+
+ @dec.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])
+
+ @dec.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])
+
+ @dec.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])
+
+ @dec.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])
+
+ @dec.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])
+
+ @dec.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])
+
+ @dec.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])
+
+
+if __name__ == "__main__":
+ run_module_suite()
diff --git a/numpy/f2py/tests/test_regression.py b/numpy/f2py/tests/test_regression.py
index b30af0c4c..43a8de350 100644
--- a/numpy/f2py/tests/test_regression.py
+++ b/numpy/f2py/tests/test_regression.py
@@ -4,7 +4,7 @@ import os
import math
import numpy as np
-from numpy.testing import dec, assert_raises, assert_equal
+from numpy.testing import run_module_suite, dec, assert_raises, assert_equal
import util
@@ -30,5 +30,4 @@ class TestIntentInOut(util.F2PyTest):
if __name__ == "__main__":
- import nose
- nose.runmodule()
+ run_module_suite()