summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Krauss <thomas.p.krauss@gmail.com>2017-03-27 08:27:52 -0500
committerTom Krauss <thomas.p.krauss@gmail.com>2017-03-27 08:27:52 -0500
commit94dcdb3d831b70d1c0f1cc2223895f0115fd6c76 (patch)
tree88b6703b6ed186c89bdcee0b8ce340b2f472c32a
parent10c4d141bb0393d3bea52a29f3068bedbb4bb2de (diff)
downloadcffi-94dcdb3d831b70d1c0f1cc2223895f0115fd6c76.tar.gz
tests pass. Had to #include <complex.h> - might want to make that optional
-rw-r--r--c/_cffi_backend.c13
-rw-r--r--c/parse_c_type.c1
-rw-r--r--cffi/_cffi_include.h27
-rw-r--r--cffi/vengine_cpy.py24
-rw-r--r--testing/cffi0/test_verify.py5
-rw-r--r--testing/cffi1/test_new_ffi_1.py2
-rw-r--r--testing/cffi1/test_realize_c_type.py8
-rw-r--r--testing/cffi1/test_verify1.py2
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():