mirror of
https://github.com/python/cpython.git
synced 2025-10-28 09:10:36 +00:00
gh-121249: Support _Complex types in the struct module (#121613)
Co-authored-by: Peter Bierma <zintensitydev@gmail.com> Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
f55273b3b7
commit
7487db4c7a
5 changed files with 321 additions and 29 deletions
|
|
@ -267,12 +267,26 @@ platform-dependent.
|
||||||
| ``P`` | :c:expr:`void \*` | integer | | \(5) |
|
| ``P`` | :c:expr:`void \*` | integer | | \(5) |
|
||||||
+--------+--------------------------+--------------------+----------------+------------+
|
+--------+--------------------------+--------------------+----------------+------------+
|
||||||
|
|
||||||
|
Additionally, if IEC 60559 compatible complex arithmetic (Annex G of the
|
||||||
|
C11 standard) is supported, the following format characters are available:
|
||||||
|
|
||||||
|
+--------+--------------------------+--------------------+----------------+------------+
|
||||||
|
| Format | C Type | Python type | Standard size | Notes |
|
||||||
|
+========+==========================+====================+================+============+
|
||||||
|
| ``E`` | :c:expr:`float complex` | complex | 8 | \(10) |
|
||||||
|
+--------+--------------------------+--------------------+----------------+------------+
|
||||||
|
| ``C`` | :c:expr:`double complex` | complex | 16 | \(10) |
|
||||||
|
+--------+--------------------------+--------------------+----------------+------------+
|
||||||
|
|
||||||
.. versionchanged:: 3.3
|
.. versionchanged:: 3.3
|
||||||
Added support for the ``'n'`` and ``'N'`` formats.
|
Added support for the ``'n'`` and ``'N'`` formats.
|
||||||
|
|
||||||
.. versionchanged:: 3.6
|
.. versionchanged:: 3.6
|
||||||
Added support for the ``'e'`` format.
|
Added support for the ``'e'`` format.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.14
|
||||||
|
Added support for the ``'E'`` and ``'C'`` formats.
|
||||||
|
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
|
|
@ -349,6 +363,11 @@ Notes:
|
||||||
of bytes. As a special case, ``'0s'`` means a single, empty string (while
|
of bytes. As a special case, ``'0s'`` means a single, empty string (while
|
||||||
``'0c'`` means 0 characters).
|
``'0c'`` means 0 characters).
|
||||||
|
|
||||||
|
(10)
|
||||||
|
For the ``'E'`` and ``'C'`` format characters, the packed representation uses
|
||||||
|
the IEEE 754 binary32 and binary64 format for components of the complex
|
||||||
|
number, regardless of the floating-point format used by the platform.
|
||||||
|
|
||||||
A format character may be preceded by an integral repeat count. For example,
|
A format character may be preceded by an integral repeat count. For example,
|
||||||
the format string ``'4h'`` means exactly the same as ``'hhhh'``.
|
the format string ``'4h'`` means exactly the same as ``'hhhh'``.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -208,8 +208,10 @@ if sizeof(c_longdouble) == sizeof(c_double):
|
||||||
try:
|
try:
|
||||||
class c_double_complex(_SimpleCData):
|
class c_double_complex(_SimpleCData):
|
||||||
_type_ = "C"
|
_type_ = "C"
|
||||||
|
_check_size(c_double_complex)
|
||||||
class c_float_complex(_SimpleCData):
|
class c_float_complex(_SimpleCData):
|
||||||
_type_ = "E"
|
_type_ = "E"
|
||||||
|
_check_size(c_float_complex)
|
||||||
class c_longdouble_complex(_SimpleCData):
|
class c_longdouble_complex(_SimpleCData):
|
||||||
_type_ = "F"
|
_type_ = "F"
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
from collections import abc
|
from collections import abc
|
||||||
|
from itertools import combinations
|
||||||
import array
|
import array
|
||||||
import gc
|
import gc
|
||||||
import math
|
import math
|
||||||
|
|
@ -11,12 +12,22 @@ import weakref
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import import_helper, suppress_immortalization
|
from test.support import import_helper, suppress_immortalization
|
||||||
from test.support.script_helper import assert_python_ok
|
from test.support.script_helper import assert_python_ok
|
||||||
|
from test.support.testcase import ComplexesAreIdenticalMixin
|
||||||
|
|
||||||
ISBIGENDIAN = sys.byteorder == "big"
|
ISBIGENDIAN = sys.byteorder == "big"
|
||||||
|
|
||||||
integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'n', 'N'
|
integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'n', 'N'
|
||||||
byteorders = '', '@', '=', '<', '>', '!'
|
byteorders = '', '@', '=', '<', '>', '!'
|
||||||
|
|
||||||
|
INF = float('inf')
|
||||||
|
NAN = float('nan')
|
||||||
|
|
||||||
|
try:
|
||||||
|
struct.pack('C', 1j)
|
||||||
|
have_c_complex = True
|
||||||
|
except struct.error:
|
||||||
|
have_c_complex = False
|
||||||
|
|
||||||
def iter_integer_formats(byteorders=byteorders):
|
def iter_integer_formats(byteorders=byteorders):
|
||||||
for code in integer_codes:
|
for code in integer_codes:
|
||||||
for byteorder in byteorders:
|
for byteorder in byteorders:
|
||||||
|
|
@ -33,7 +44,7 @@ def bigendian_to_native(value):
|
||||||
else:
|
else:
|
||||||
return string_reverse(value)
|
return string_reverse(value)
|
||||||
|
|
||||||
class StructTest(unittest.TestCase):
|
class StructTest(ComplexesAreIdenticalMixin, unittest.TestCase):
|
||||||
def test_isbigendian(self):
|
def test_isbigendian(self):
|
||||||
self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN)
|
self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN)
|
||||||
|
|
||||||
|
|
@ -783,6 +794,30 @@ class StructTest(unittest.TestCase):
|
||||||
s = struct.Struct('=i2H')
|
s = struct.Struct('=i2H')
|
||||||
self.assertEqual(repr(s), f'Struct({s.format!r})')
|
self.assertEqual(repr(s), f'Struct({s.format!r})')
|
||||||
|
|
||||||
|
@unittest.skipUnless(have_c_complex, "requires C11 complex type support")
|
||||||
|
def test_c_complex_round_trip(self):
|
||||||
|
values = [complex(*_) for _ in combinations([1, -1, 0.0, -0.0, 2,
|
||||||
|
-3, INF, -INF, NAN], 2)]
|
||||||
|
for z in values:
|
||||||
|
for f in ['E', 'C', '>E', '>C', '<E', '<C']:
|
||||||
|
with self.subTest(z=z, format=f):
|
||||||
|
round_trip = struct.unpack(f, struct.pack(f, z))[0]
|
||||||
|
self.assertComplexesAreIdentical(z, round_trip)
|
||||||
|
|
||||||
|
@unittest.skipIf(have_c_complex, "requires no C11 complex type support")
|
||||||
|
def test_c_complex_error(self):
|
||||||
|
msg1 = "'E' format not supported on this system"
|
||||||
|
msg2 = "'C' format not supported on this system"
|
||||||
|
with self.assertRaisesRegex(struct.error, msg1):
|
||||||
|
struct.pack('E', 1j)
|
||||||
|
with self.assertRaisesRegex(struct.error, msg1):
|
||||||
|
struct.unpack('E', b'1')
|
||||||
|
with self.assertRaisesRegex(struct.error, msg2):
|
||||||
|
struct.pack('C', 1j)
|
||||||
|
with self.assertRaisesRegex(struct.error, msg2):
|
||||||
|
struct.unpack('C', b'1')
|
||||||
|
|
||||||
|
|
||||||
class UnpackIteratorTest(unittest.TestCase):
|
class UnpackIteratorTest(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
Tests for iterative unpacking (struct.Struct.iter_unpack).
|
Tests for iterative unpacking (struct.Struct.iter_unpack).
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
Support the :c:expr:`float complex` and :c:expr:`double complex`
|
||||||
|
C types in the :mod:`struct` module if the compiler has C11 complex
|
||||||
|
arithmetic. Patch by Sergey B Kirpichev.
|
||||||
|
|
@ -12,6 +12,9 @@
|
||||||
#include "pycore_long.h" // _PyLong_AsByteArray()
|
#include "pycore_long.h" // _PyLong_AsByteArray()
|
||||||
#include "pycore_moduleobject.h" // _PyModule_GetState()
|
#include "pycore_moduleobject.h" // _PyModule_GetState()
|
||||||
|
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
# include "_complex.h" // complex
|
||||||
|
#endif
|
||||||
#include <stddef.h> // offsetof()
|
#include <stddef.h> // offsetof()
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
|
@ -80,6 +83,10 @@ typedef struct { char c; int x; } st_int;
|
||||||
typedef struct { char c; long x; } st_long;
|
typedef struct { char c; long x; } st_long;
|
||||||
typedef struct { char c; float x; } st_float;
|
typedef struct { char c; float x; } st_float;
|
||||||
typedef struct { char c; double x; } st_double;
|
typedef struct { char c; double x; } st_double;
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
typedef struct { char c; float complex x; } st_float_complex;
|
||||||
|
typedef struct { char c; double complex x; } st_double_complex;
|
||||||
|
#endif
|
||||||
typedef struct { char c; void *x; } st_void_p;
|
typedef struct { char c; void *x; } st_void_p;
|
||||||
typedef struct { char c; size_t x; } st_size_t;
|
typedef struct { char c; size_t x; } st_size_t;
|
||||||
typedef struct { char c; _Bool x; } st_bool;
|
typedef struct { char c; _Bool x; } st_bool;
|
||||||
|
|
@ -89,6 +96,10 @@ typedef struct { char c; _Bool x; } st_bool;
|
||||||
#define LONG_ALIGN (sizeof(st_long) - sizeof(long))
|
#define LONG_ALIGN (sizeof(st_long) - sizeof(long))
|
||||||
#define FLOAT_ALIGN (sizeof(st_float) - sizeof(float))
|
#define FLOAT_ALIGN (sizeof(st_float) - sizeof(float))
|
||||||
#define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double))
|
#define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double))
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
# define FLOAT_COMPLEX_ALIGN (sizeof(st_float_complex) - sizeof(float complex))
|
||||||
|
# define DOUBLE_COMPLEX_ALIGN (sizeof(st_double_complex) - sizeof(double complex))
|
||||||
|
#endif
|
||||||
#define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *))
|
#define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *))
|
||||||
#define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t))
|
#define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t))
|
||||||
#define BOOL_ALIGN (sizeof(st_bool) - sizeof(_Bool))
|
#define BOOL_ALIGN (sizeof(st_bool) - sizeof(_Bool))
|
||||||
|
|
@ -407,7 +418,7 @@ static PyObject *
|
||||||
nu_short(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_short(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
short x;
|
short x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromLong((long)x);
|
return PyLong_FromLong((long)x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -415,7 +426,7 @@ static PyObject *
|
||||||
nu_ushort(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_ushort(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
unsigned short x;
|
unsigned short x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromLong((long)x);
|
return PyLong_FromLong((long)x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -423,7 +434,7 @@ static PyObject *
|
||||||
nu_int(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_int(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromLong((long)x);
|
return PyLong_FromLong((long)x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,7 +442,7 @@ static PyObject *
|
||||||
nu_uint(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_uint(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromUnsignedLong((unsigned long)x);
|
return PyLong_FromUnsignedLong((unsigned long)x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -439,7 +450,7 @@ static PyObject *
|
||||||
nu_long(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_long(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
long x;
|
long x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromLong(x);
|
return PyLong_FromLong(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -447,7 +458,7 @@ static PyObject *
|
||||||
nu_ulong(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_ulong(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
unsigned long x;
|
unsigned long x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromUnsignedLong(x);
|
return PyLong_FromUnsignedLong(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -455,7 +466,7 @@ static PyObject *
|
||||||
nu_ssize_t(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_ssize_t(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
Py_ssize_t x;
|
Py_ssize_t x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromSsize_t(x);
|
return PyLong_FromSsize_t(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -463,7 +474,7 @@ static PyObject *
|
||||||
nu_size_t(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_size_t(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
size_t x;
|
size_t x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromSize_t(x);
|
return PyLong_FromSize_t(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,7 +482,7 @@ static PyObject *
|
||||||
nu_longlong(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_longlong(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
long long x;
|
long long x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromLongLong(x);
|
return PyLong_FromLongLong(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -479,7 +490,7 @@ static PyObject *
|
||||||
nu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
unsigned long long x;
|
unsigned long long x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromUnsignedLongLong(x);
|
return PyLong_FromUnsignedLongLong(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -487,7 +498,7 @@ static PyObject *
|
||||||
nu_bool(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_bool(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
_Bool x;
|
_Bool x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyBool_FromLong(x != 0);
|
return PyBool_FromLong(x != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -506,7 +517,7 @@ static PyObject *
|
||||||
nu_float(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_float(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
float x;
|
float x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyFloat_FromDouble((double)x);
|
return PyFloat_FromDouble((double)x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -514,15 +525,35 @@ static PyObject *
|
||||||
nu_double(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_double(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
double x;
|
double x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyFloat_FromDouble(x);
|
return PyFloat_FromDouble(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
static PyObject *
|
||||||
|
nu_float_complex(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
|
{
|
||||||
|
float complex x;
|
||||||
|
|
||||||
|
memcpy(&x, p, sizeof(x));
|
||||||
|
return PyComplex_FromDoubles(creal(x), cimag(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
nu_double_complex(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
|
{
|
||||||
|
double complex x;
|
||||||
|
|
||||||
|
memcpy(&x, p, sizeof(x));
|
||||||
|
return PyComplex_FromDoubles(creal(x), cimag(x));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
nu_void_p(_structmodulestate *state, const char *p, const formatdef *f)
|
nu_void_p(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
void *x;
|
void *x;
|
||||||
memcpy((char *)&x, p, sizeof x);
|
memcpy(&x, p, sizeof x);
|
||||||
return PyLong_FromVoidPtr(x);
|
return PyLong_FromVoidPtr(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -587,7 +618,7 @@ np_short(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
RANGE_ERROR(state, f, 0);
|
RANGE_ERROR(state, f, 0);
|
||||||
}
|
}
|
||||||
y = (short)x;
|
y = (short)x;
|
||||||
memcpy(p, (char *)&y, sizeof y);
|
memcpy(p, &y, sizeof y);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -606,7 +637,7 @@ np_ushort(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
RANGE_ERROR(state, f, 1);
|
RANGE_ERROR(state, f, 1);
|
||||||
}
|
}
|
||||||
y = (unsigned short)x;
|
y = (unsigned short)x;
|
||||||
memcpy(p, (char *)&y, sizeof y);
|
memcpy(p, &y, sizeof y);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -626,7 +657,7 @@ np_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
RANGE_ERROR(state, f, 0);
|
RANGE_ERROR(state, f, 0);
|
||||||
#endif
|
#endif
|
||||||
y = (int)x;
|
y = (int)x;
|
||||||
memcpy(p, (char *)&y, sizeof y);
|
memcpy(p, &y, sizeof y);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -646,7 +677,7 @@ np_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
if (x > ((unsigned long)UINT_MAX))
|
if (x > ((unsigned long)UINT_MAX))
|
||||||
RANGE_ERROR(state, f, 1);
|
RANGE_ERROR(state, f, 1);
|
||||||
#endif
|
#endif
|
||||||
memcpy(p, (char *)&y, sizeof y);
|
memcpy(p, &y, sizeof y);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -660,7 +691,7 @@ np_long(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(p, (char *)&x, sizeof x);
|
memcpy(p, &x, sizeof x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -674,7 +705,7 @@ np_ulong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(p, (char *)&x, sizeof x);
|
memcpy(p, &x, sizeof x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -688,7 +719,7 @@ np_ssize_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(p, (char *)&x, sizeof x);
|
memcpy(p, &x, sizeof x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -702,7 +733,7 @@ np_size_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(p, (char *)&x, sizeof x);
|
memcpy(p, &x, sizeof x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -720,7 +751,7 @@ np_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(p, (char *)&x, sizeof x);
|
memcpy(p, &x, sizeof x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -737,7 +768,7 @@ np_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(p, (char *)&x, sizeof x);
|
memcpy(p, &x, sizeof x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -751,7 +782,7 @@ np_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
if (y < 0)
|
if (y < 0)
|
||||||
return -1;
|
return -1;
|
||||||
x = y;
|
x = y;
|
||||||
memcpy(p, (char *)&x, sizeof x);
|
memcpy(p, &x, sizeof x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -774,7 +805,7 @@ np_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
"required argument is not a float");
|
"required argument is not a float");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(p, (char *)&x, sizeof x);
|
memcpy(p, &x, sizeof x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -787,10 +818,62 @@ np_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
"required argument is not a float");
|
"required argument is not a float");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(p, (char *)&x, sizeof(double));
|
memcpy(p, &x, sizeof(double));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
static int
|
||||||
|
np_float_complex(_structmodulestate *state, char *p, PyObject *v,
|
||||||
|
const formatdef *f)
|
||||||
|
{
|
||||||
|
Py_complex c = PyComplex_AsCComplex(v);
|
||||||
|
float complex x = CMPLXF((float)c.real, (float)c.imag);
|
||||||
|
|
||||||
|
if (c.real == -1 && PyErr_Occurred()) {
|
||||||
|
PyErr_SetString(state->StructError,
|
||||||
|
"required argument is not a complex");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(p, &x, sizeof(x));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
np_double_complex(_structmodulestate *state, char *p, PyObject *v,
|
||||||
|
const formatdef *f)
|
||||||
|
{
|
||||||
|
Py_complex c = PyComplex_AsCComplex(v);
|
||||||
|
double complex x = CMPLX(c.real, c.imag);
|
||||||
|
|
||||||
|
if (c.real == -1 && PyErr_Occurred()) {
|
||||||
|
PyErr_SetString(state->StructError,
|
||||||
|
"required argument is not a complex");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(p, &x, sizeof(x));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int
|
||||||
|
np_complex_stub(_structmodulestate *state, char *p, PyObject *v,
|
||||||
|
const formatdef *f)
|
||||||
|
{
|
||||||
|
PyErr_Format(state->StructError,
|
||||||
|
"'%c' format not supported on this system",
|
||||||
|
f->format);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static PyObject *
|
||||||
|
nu_complex_stub(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
|
{
|
||||||
|
PyErr_Format(state->StructError,
|
||||||
|
"'%c' format not supported on this system",
|
||||||
|
f->format);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
np_void_p(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
np_void_p(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
{
|
{
|
||||||
|
|
@ -804,7 +887,7 @@ np_void_p(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
if (x == NULL && PyErr_Occurred())
|
if (x == NULL && PyErr_Occurred())
|
||||||
return -1;
|
return -1;
|
||||||
memcpy(p, (char *)&x, sizeof x);
|
memcpy(p, &x, sizeof x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -829,6 +912,13 @@ static const formatdef native_table[] = {
|
||||||
{'e', sizeof(short), SHORT_ALIGN, nu_halffloat, np_halffloat},
|
{'e', sizeof(short), SHORT_ALIGN, nu_halffloat, np_halffloat},
|
||||||
{'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
|
{'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float},
|
||||||
{'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
|
{'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double},
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
{'E', sizeof(float complex), FLOAT_COMPLEX_ALIGN, nu_float_complex, np_float_complex},
|
||||||
|
{'C', sizeof(double complex), DOUBLE_COMPLEX_ALIGN, nu_double_complex, np_double_complex},
|
||||||
|
#else
|
||||||
|
{'E', 1, 0, nu_complex_stub, np_complex_stub},
|
||||||
|
{'C', 1, 0, nu_complex_stub, np_complex_stub},
|
||||||
|
#endif
|
||||||
{'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p},
|
{'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
@ -929,6 +1019,38 @@ bu_double(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
return unpack_double(p, 0);
|
return unpack_double(p, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
static PyObject *
|
||||||
|
bu_float_complex(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
|
{
|
||||||
|
double x = PyFloat_Unpack4(p, 0);
|
||||||
|
if (x == -1.0 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
double y = PyFloat_Unpack4(p + 4, 0);
|
||||||
|
if (y == -1.0 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return PyComplex_FromDoubles(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
bu_double_complex(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
|
||||||
|
x = PyFloat_Unpack8(p, 0);
|
||||||
|
if (x == -1.0 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
y = PyFloat_Unpack8(p + 8, 0);
|
||||||
|
if (y == -1.0 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return PyComplex_FromDoubles(x, y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bu_bool(_structmodulestate *state, const char *p, const formatdef *f)
|
bu_bool(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
{
|
{
|
||||||
|
|
@ -1068,6 +1190,38 @@ bp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
return PyFloat_Pack8(x, p, 0);
|
return PyFloat_Pack8(x, p, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
static int
|
||||||
|
bp_float_complex(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
|
{
|
||||||
|
Py_complex x = PyComplex_AsCComplex(v);
|
||||||
|
if (x.real == -1 && PyErr_Occurred()) {
|
||||||
|
PyErr_SetString(state->StructError,
|
||||||
|
"required argument is not a complex");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (PyFloat_Pack4(x.real, p, 0)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return PyFloat_Pack4(x.imag, p + 4, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bp_double_complex(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
|
{
|
||||||
|
Py_complex x = PyComplex_AsCComplex(v);
|
||||||
|
if (x.real == -1 && PyErr_Occurred()) {
|
||||||
|
PyErr_SetString(state->StructError,
|
||||||
|
"required argument is not a complex");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (PyFloat_Pack8(x.real, p, 0)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return PyFloat_Pack8(x.imag, p + 8, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bp_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
bp_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
{
|
{
|
||||||
|
|
@ -1098,6 +1252,13 @@ static formatdef bigendian_table[] = {
|
||||||
{'e', 2, 0, bu_halffloat, bp_halffloat},
|
{'e', 2, 0, bu_halffloat, bp_halffloat},
|
||||||
{'f', 4, 0, bu_float, bp_float},
|
{'f', 4, 0, bu_float, bp_float},
|
||||||
{'d', 8, 0, bu_double, bp_double},
|
{'d', 8, 0, bu_double, bp_double},
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
{'E', 8, 0, bu_float_complex, bp_float_complex},
|
||||||
|
{'C', 16, 0, bu_double_complex, bp_double_complex},
|
||||||
|
#else
|
||||||
|
{'E', 1, 0, nu_complex_stub, np_complex_stub},
|
||||||
|
{'C', 1, 0, nu_complex_stub, np_complex_stub},
|
||||||
|
#endif
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1197,6 +1358,38 @@ lu_double(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
return unpack_double(p, 1);
|
return unpack_double(p, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
static PyObject *
|
||||||
|
lu_float_complex(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
|
{
|
||||||
|
double x = PyFloat_Unpack4(p, 1);
|
||||||
|
if (x == -1.0 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
double y = PyFloat_Unpack4(p + 4, 1);
|
||||||
|
if (y == -1.0 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return PyComplex_FromDoubles(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
lu_double_complex(_structmodulestate *state, const char *p, const formatdef *f)
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
|
||||||
|
x = PyFloat_Unpack8(p, 1);
|
||||||
|
if (x == -1.0 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
y = PyFloat_Unpack8(p + 8, 1);
|
||||||
|
if (y == -1.0 && PyErr_Occurred()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return PyComplex_FromDoubles(x, y);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
lp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
{
|
{
|
||||||
|
|
@ -1330,6 +1523,39 @@ lp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
return PyFloat_Pack8(x, p, 1);
|
return PyFloat_Pack8(x, p, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
static int
|
||||||
|
lp_float_complex(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
|
{
|
||||||
|
Py_complex x = PyComplex_AsCComplex(v);
|
||||||
|
if (x.real == -1 && PyErr_Occurred()) {
|
||||||
|
PyErr_SetString(state->StructError,
|
||||||
|
"required argument is not a complex");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (PyFloat_Pack4(x.real, p, 1)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return PyFloat_Pack4(x.imag, p + 4, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lp_double_complex(_structmodulestate *state, char *p, PyObject *v, const formatdef *f)
|
||||||
|
{
|
||||||
|
Py_complex x = PyComplex_AsCComplex(v);
|
||||||
|
if (x.real == -1 && PyErr_Occurred()) {
|
||||||
|
PyErr_SetString(state->StructError,
|
||||||
|
"required argument is not a complex");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (PyFloat_Pack8(x.real, p, 1)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return PyFloat_Pack8(x.imag, p + 8, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static formatdef lilendian_table[] = {
|
static formatdef lilendian_table[] = {
|
||||||
{'x', 1, 0, NULL},
|
{'x', 1, 0, NULL},
|
||||||
{'b', 1, 0, nu_byte, np_byte},
|
{'b', 1, 0, nu_byte, np_byte},
|
||||||
|
|
@ -1350,6 +1576,13 @@ static formatdef lilendian_table[] = {
|
||||||
{'e', 2, 0, lu_halffloat, lp_halffloat},
|
{'e', 2, 0, lu_halffloat, lp_halffloat},
|
||||||
{'f', 4, 0, lu_float, lp_float},
|
{'f', 4, 0, lu_float, lp_float},
|
||||||
{'d', 8, 0, lu_double, lp_double},
|
{'d', 8, 0, lu_double, lp_double},
|
||||||
|
#ifdef Py_HAVE_C_COMPLEX
|
||||||
|
{'E', 8, 0, lu_float_complex, lp_float_complex},
|
||||||
|
{'C', 16, 0, lu_double_complex, lp_double_complex},
|
||||||
|
#else
|
||||||
|
{'E', 1, 0, nu_complex_stub, np_complex_stub},
|
||||||
|
{'C', 1, 0, nu_complex_stub, np_complex_stub},
|
||||||
|
#endif
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue