diff options
author | Tom Krauss <thomas.p.krauss@gmail.com> | 2017-03-27 08:27:52 -0500 |
---|---|---|
committer | Tom Krauss <thomas.p.krauss@gmail.com> | 2017-03-27 08:27:52 -0500 |
commit | 94dcdb3d831b70d1c0f1cc2223895f0115fd6c76 (patch) | |
tree | 88b6703b6ed186c89bdcee0b8ce340b2f472c32a | |
parent | 10c4d141bb0393d3bea52a29f3068bedbb4bb2de (diff) | |
download | cffi-94dcdb3d831b70d1c0f1cc2223895f0115fd6c76.tar.gz |
tests pass. Had to #include <complex.h> - might want to make that optional
-rw-r--r-- | c/_cffi_backend.c | 13 | ||||
-rw-r--r-- | c/parse_c_type.c | 1 | ||||
-rw-r--r-- | cffi/_cffi_include.h | 27 | ||||
-rw-r--r-- | cffi/vengine_cpy.py | 24 | ||||
-rw-r--r-- | testing/cffi0/test_verify.py | 5 | ||||
-rw-r--r-- | testing/cffi1/test_new_ffi_1.py | 2 | ||||
-rw-r--r-- | testing/cffi1/test_realize_c_type.py | 8 | ||||
-rw-r--r-- | testing/cffi1/test_verify1.py | 2 |
8 files changed, 73 insertions, 9 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c index 87654f1..358c4a4 100644 --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -2964,9 +2964,20 @@ static PyObject *cdata_complex(PyObject *cd_, PyObject *noarg) if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) { Py_complex value = read_raw_complex_data(cd->c_data, cd->c_type->ct_size); PyObject *op = PyComplex_FromCComplex(value); - PyComplexObject *opc = (PyComplexObject *) op; return op; } + // floats can also be converted to complex + if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) { + Py_complex value; + if (!(cd->c_type->ct_flags & CT_IS_LONGDOUBLE)) { + value.real = read_raw_float_data(cd->c_data, cd->c_type->ct_size); + } + else { + value.real = (double)read_raw_longdouble_data(cd->c_data); + } + value.imag = 0.0; + return PyComplex_FromCComplex(value); + } PyErr_Format(PyExc_TypeError, "complex() not supported on cdata '%s'", cd->c_type->ct_name); return NULL; diff --git a/c/parse_c_type.c b/c/parse_c_type.c index 15c6b0c..8a11da6 100644 --- a/c/parse_c_type.c +++ b/c/parse_c_type.c @@ -797,7 +797,6 @@ static int parse_c_type_from(struct _cffi_parse_info_s *info, size_t *output_index, const char *input) { - printf("parse_c_type_from\n"); int result; token_t token; diff --git a/cffi/_cffi_include.h b/cffi/_cffi_include.h index fdfd21a..261e6a5 100644 --- a/cffi/_cffi_include.h +++ b/cffi/_cffi_include.h @@ -16,6 +16,7 @@ #endif #include <Python.h> +#include <complex.h> #ifdef __cplusplus extern "C" { #endif @@ -99,6 +100,29 @@ extern "C" { #define _cffi_to_c_double PyFloat_AsDouble #define _cffi_to_c_float PyFloat_AsDouble +#define _cffi_from_c_float__Complex(x) PyComplex_FromDoubles(crealf(x), cimagf(x)) +#define _cffi_from_c_double__Complex(x) PyComplex_FromDoubles(creal(x), cimag(x)) + +/* inefficient - converts twice! */ +#define _cffi_to_c_float__Complex(op) \ + ( ((float)(PyComplex_AsCComplex(op).real)) + \ + I*((float)(PyComplex_AsCComplex(op).imag)) ) +/* not safe! +//#define _cffi_to_c_float__Complex(op) \ +// ( ((float)((PyComplexObject *)(op))->cval.real) + \ +// I*((float)((PyComplexObject *)(op))->cval.imag) ) +*/ + +/* inefficient - converts twice! */ +#define _cffi_to_c_double__Complex(op) \ + ( (PyComplex_AsCComplex(op).real) + \ + I*(PyComplex_AsCComplex(op).imag) ) +/* not safe! +//#define _cffi_to_c_double__Complex(op) \ +// ( (((PyComplexObject *)(op))->cval.real) + \ +// I*(((PyComplexObject *)(op))->cval.imag) ) +*/ + #define _cffi_from_c_int(x, type) \ (((type)-1) > 0 ? /* unsigned */ \ (sizeof(type) < sizeof(long) ? \ @@ -110,9 +134,6 @@ extern "C" { PyInt_FromLong((long)x) : \ PyLong_FromLongLong((long long)x))) -#define _cffi_from_c_float__Complex(x) PyComplex_FromDoubles(crealf(x), cimagf(x)) -#define _cffi_from_c_double__Complex(x) PyComplex_FromDoubles(creal(x), cimag(x)) - #define _cffi_to_c_int(o, type) \ ((type)( \ sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ diff --git a/cffi/vengine_cpy.py b/cffi/vengine_cpy.py index af8775f..9ba8b1d 100644 --- a/cffi/vengine_cpy.py +++ b/cffi/vengine_cpy.py @@ -806,6 +806,7 @@ class VCPythonEngine(object): cffimod_header = r''' #include <Python.h> #include <stddef.h> +#include <complex.h> /* this block of #ifs should be kept exactly identical between c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py */ @@ -873,6 +874,29 @@ cffimod_header = r''' #define _cffi_to_c_double PyFloat_AsDouble #define _cffi_to_c_float PyFloat_AsDouble +#define _cffi_from_c_float__Complex(x) PyComplex_FromDoubles(crealf(x), cimagf(x)) +#define _cffi_from_c_double__Complex(x) PyComplex_FromDoubles(creal(x), cimag(x)) + +/* inefficient - converts twice! */ +#define _cffi_to_c_float__Complex(op) \ + ( ((float)(PyComplex_AsCComplex(op).real)) + \ + I*((float)(PyComplex_AsCComplex(op).imag)) ) +/* not safe! +//#define _cffi_to_c_float__Complex(op) \ +// ( ((float)((PyComplexObject *)(op))->cval.real) + \ +// I*((float)((PyComplexObject *)(op))->cval.imag) ) +*/ + +/* inefficient - converts twice! */ +#define _cffi_to_c_double__Complex(op) \ + ( (PyComplex_AsCComplex(op).real) + \ + I*(PyComplex_AsCComplex(op).imag) ) +/* not safe! +//#define _cffi_to_c_double__Complex(op) \ +// ( (((PyComplexObject *)(op))->cval.real) + \ +// I*(((PyComplexObject *)(op))->cval.imag) ) +*/ + #define _cffi_from_c_int_const(x) \ (((x) > 0) ? \ ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \ diff --git a/testing/cffi0/test_verify.py b/testing/cffi0/test_verify.py index 25430bd..53c3f3f 100644 --- a/testing/cffi0/test_verify.py +++ b/testing/cffi0/test_verify.py @@ -241,14 +241,15 @@ def test_primitive_category(): F = tp.is_float_type() I = tp.is_integer_type() assert C == (typename in ('char', 'wchar_t')) - assert F == (typename in ('float', 'double', 'long double')) + assert F == (typename in ('float', 'double', 'long double', 'float _Complex', 'double _Complex')) assert I + F + C == 1 # one and only one of them is true def test_all_integer_and_float_types(): typenames = [] for typename in all_primitive_types: if (all_primitive_types[typename] == 'c' or - typename == '_Bool' or typename == 'long double'): + typename == '_Bool' or typename == 'long double' + or '_Complex' in typename): # omit _Complex since ffi does not yet support pass else: typenames.append(typename) diff --git a/testing/cffi1/test_new_ffi_1.py b/testing/cffi1/test_new_ffi_1.py index a1856a6..6e42571 100644 --- a/testing/cffi1/test_new_ffi_1.py +++ b/testing/cffi1/test_new_ffi_1.py @@ -1704,6 +1704,8 @@ class TestNewFFI1: "ptrdiff_t", "size_t", "ssize_t", + 'double _Complex', + 'float _Complex', ]) for name in PRIMITIVE_TO_INDEX: x = ffi.sizeof(name) diff --git a/testing/cffi1/test_realize_c_type.py b/testing/cffi1/test_realize_c_type.py index 40b1e9b..bddb38c 100644 --- a/testing/cffi1/test_realize_c_type.py +++ b/testing/cffi1/test_realize_c_type.py @@ -45,8 +45,14 @@ def test_funcptr_rewrite_args(): def test_all_primitives(): for name in cffi_opcode.PRIMITIVE_TO_INDEX: - check(name, name) + if '_Complex' not in name: + check(name, name) +def test_complex_primitives(): + py.test.xfail("ffi does not support complex yet") + for name in cffi_opcode.PRIMITIVE_TO_INDEX: + if '_Complex' in name: + check(name, name) def check_func(input, expected_output=None): import _cffi_backend diff --git a/testing/cffi1/test_verify1.py b/testing/cffi1/test_verify1.py index aaeb244..72ddc49 100644 --- a/testing/cffi1/test_verify1.py +++ b/testing/cffi1/test_verify1.py @@ -221,7 +221,7 @@ def test_primitive_category(): F = tp.is_float_type() I = tp.is_integer_type() assert C == (typename in ('char', 'wchar_t')) - assert F == (typename in ('float', 'double', 'long double')) + assert F == (typename in ('float', 'double', 'long double', 'float _Complex', 'double _Complex')) assert I + F + C == 1 # one and only one of them is true def test_all_integer_and_float_types(): |