From 89ca6a28fb5bb7b68e7b60789c1807d0c1652c2e Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 24 Apr 2025 08:37:34 +0300 Subject: [PATCH 01/10] gh-121249: make complex types available unconditionally in the struct module Each complex type interpreted as an array type containing exactly two elements of the corresponding real type (real and imaginary parts, respectively). --- Doc/library/struct.rst | 13 ++++---- Doc/whatsnew/3.14.rst | 3 +- Modules/_struct.c | 76 +++++++----------------------------------- 3 files changed, 19 insertions(+), 73 deletions(-) diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index 071b90b9359fa5..71c0aa4afaecda 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -266,13 +266,6 @@ platform-dependent. +--------+--------------------------+--------------------+----------------+------------+ | ``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 | -+========+==========================+====================+================+============+ | ``F`` | :c:expr:`float complex` | complex | 8 | \(10) | +--------+--------------------------+--------------------+----------------+------------+ | ``D`` | :c:expr:`double complex` | complex | 16 | \(10) | @@ -367,6 +360,12 @@ Notes: 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. + Note, that support for complex types is available unconditionally, + regardless on support IEC 60559 compatible complex arithmetic (Annex G of + the C11 standard) by the compiler. Each complex type interpreted as an + array type containing exactly two elements of the corresponding real type + (real and imaginary parts, respectively). + A format character may be preceded by an integral repeat count. For example, the format string ``'4h'`` means exactly the same as ``'hhhh'``. diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 5b03bd9e5a8caf..11a7ac45de77fa 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1173,8 +1173,7 @@ struct ------ * Support the :c:expr:`float complex` and :c:expr:`double complex` C types in - the :mod:`struct` module (formatting characters ``'F'`` and ``'D'``, - respectively) if the compiler has C11 complex arithmetic. + the :mod:`struct` module (formatting characters ``'F'`` and ``'D'``. (Contributed by Sergey B Kirpichev in :gh:`121249`.) diff --git a/Modules/_struct.c b/Modules/_struct.c index 9910986a39570f..186a92c6ada606 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -12,9 +12,6 @@ #include "pycore_long.h" // _PyLong_AsByteArray() #include "pycore_moduleobject.h" // _PyModule_GetState() -#ifdef Py_HAVE_C_COMPLEX -# include "_complex.h" // complex -#endif #include // offsetof() /*[clinic input] @@ -84,10 +81,8 @@ typedef struct { char c; int x; } st_int; typedef struct { char c; long x; } st_long; typedef struct { char c; float x; } st_float; 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; float x[2]; } st_float_complex; +typedef struct { char c; double x[2]; } st_double_complex; typedef struct { char c; void *x; } st_void_p; typedef struct { char c; size_t x; } st_size_t; typedef struct { char c; _Bool x; } st_bool; @@ -97,10 +92,8 @@ typedef struct { char c; _Bool x; } st_bool; #define LONG_ALIGN (sizeof(st_long) - sizeof(long)) #define FLOAT_ALIGN (sizeof(st_float) - sizeof(float)) #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 FLOAT_COMPLEX_ALIGN (sizeof(st_float_complex) - 2*sizeof(float)) +#define DOUBLE_COMPLEX_ALIGN (sizeof(st_double_complex) - 2*sizeof(double)) #define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *)) #define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t)) #define BOOL_ALIGN (sizeof(st_bool) - sizeof(_Bool)) @@ -529,25 +522,23 @@ nu_double(_structmodulestate *state, const char *p, const formatdef *f) 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; + float x[2]; memcpy(&x, p, sizeof(x)); - return PyComplex_FromDoubles(creal(x), cimag(x)); + return PyComplex_FromDoubles(x[0], x[1]); } static PyObject * nu_double_complex(_structmodulestate *state, const char *p, const formatdef *f) { - double complex x; + double x[2]; memcpy(&x, p, sizeof(x)); - return PyComplex_FromDoubles(creal(x), cimag(x)); + return PyComplex_FromDoubles(x[0], x[1]); } -#endif static PyObject * nu_void_p(_structmodulestate *state, const char *p, const formatdef *f) @@ -822,13 +813,12 @@ np_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) 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); + float x[2] = {(float)c.real, (float)c.imag}; if (c.real == -1 && PyErr_Occurred()) { PyErr_SetString(state->StructError, @@ -844,7 +834,7 @@ 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); + double x[2] = {c.real, c.imag}; if (c.real == -1 && PyErr_Occurred()) { PyErr_SetString(state->StructError, @@ -854,25 +844,6 @@ np_double_complex(_structmodulestate *state, char *p, PyObject *v, 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 np_void_p(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) @@ -912,13 +883,8 @@ static const formatdef native_table[] = { {'e', sizeof(short), SHORT_ALIGN, nu_halffloat, np_halffloat}, {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float}, {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double}, -#ifdef Py_HAVE_C_COMPLEX - {'F', sizeof(float complex), FLOAT_COMPLEX_ALIGN, nu_float_complex, np_float_complex}, - {'D', sizeof(double complex), DOUBLE_COMPLEX_ALIGN, nu_double_complex, np_double_complex}, -#else - {'F', 1, 0, nu_complex_stub, np_complex_stub}, - {'D', 1, 0, nu_complex_stub, np_complex_stub}, -#endif + {'F', 2*sizeof(float), FLOAT_COMPLEX_ALIGN, nu_float_complex, np_float_complex}, + {'D', 2*sizeof(double), DOUBLE_COMPLEX_ALIGN, nu_double_complex, np_double_complex}, {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p}, {0} }; @@ -1019,7 +985,6 @@ bu_double(_structmodulestate *state, const char *p, const formatdef *f) return unpack_double(p, 0); } -#ifdef Py_HAVE_C_COMPLEX static PyObject * bu_float_complex(_structmodulestate *state, const char *p, const formatdef *f) { @@ -1049,7 +1014,6 @@ bu_double_complex(_structmodulestate *state, const char *p, const formatdef *f) } return PyComplex_FromDoubles(x, y); } -#endif static PyObject * bu_bool(_structmodulestate *state, const char *p, const formatdef *f) @@ -1190,7 +1154,6 @@ bp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) 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) { @@ -1220,7 +1183,6 @@ bp_double_complex(_structmodulestate *state, char *p, PyObject *v, const formatd } return PyFloat_Pack8(x.imag, p + 8, 0); } -#endif static int bp_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) @@ -1252,13 +1214,8 @@ static formatdef bigendian_table[] = { {'e', 2, 0, bu_halffloat, bp_halffloat}, {'f', 4, 0, bu_float, bp_float}, {'d', 8, 0, bu_double, bp_double}, -#ifdef Py_HAVE_C_COMPLEX {'F', 8, 0, bu_float_complex, bp_float_complex}, {'D', 16, 0, bu_double_complex, bp_double_complex}, -#else - {'F', 1, 0, nu_complex_stub, np_complex_stub}, - {'D', 1, 0, nu_complex_stub, np_complex_stub}, -#endif {0} }; @@ -1358,7 +1315,6 @@ lu_double(_structmodulestate *state, const char *p, const formatdef *f) return unpack_double(p, 1); } -#ifdef Py_HAVE_C_COMPLEX static PyObject * lu_float_complex(_structmodulestate *state, const char *p, const formatdef *f) { @@ -1388,7 +1344,6 @@ lu_double_complex(_structmodulestate *state, const char *p, const formatdef *f) } return PyComplex_FromDoubles(x, y); } -#endif static int lp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) @@ -1523,7 +1478,6 @@ lp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) 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) { @@ -1554,7 +1508,6 @@ lp_double_complex(_structmodulestate *state, char *p, PyObject *v, const formatd } return PyFloat_Pack8(x.imag, p + 8, 1); } -#endif static formatdef lilendian_table[] = { {'x', 1, 0, NULL}, @@ -1576,13 +1529,8 @@ static formatdef lilendian_table[] = { {'e', 2, 0, lu_halffloat, lp_halffloat}, {'f', 4, 0, lu_float, lp_float}, {'d', 8, 0, lu_double, lp_double}, -#ifdef Py_HAVE_C_COMPLEX {'F', 8, 0, lu_float_complex, lp_float_complex}, {'D', 16, 0, lu_double_complex, lp_double_complex}, -#else - {'F', 1, 0, nu_complex_stub, np_complex_stub}, - {'D', 1, 0, nu_complex_stub, np_complex_stub}, -#endif {0} }; From e287449f20cce560147e487e7a726ae72b75d696 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 24 Apr 2025 09:45:16 +0300 Subject: [PATCH 02/10] Apply suggestions from code review Co-authored-by: Lisandro Dalcin --- Doc/library/struct.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index 71c0aa4afaecda..5e3cda6279c975 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -360,9 +360,9 @@ Notes: 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. - Note, that support for complex types is available unconditionally, + Note that support for complex types is available unconditionally, regardless on support IEC 60559 compatible complex arithmetic (Annex G of - the C11 standard) by the compiler. Each complex type interpreted as an + the C11 standard) by the compiler. Each complex type is interpreted as an array type containing exactly two elements of the corresponding real type (real and imaginary parts, respectively). From 78ff9029676279cfb1100c920398e16eab571c6e Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 24 Apr 2025 10:09:29 +0300 Subject: [PATCH 03/10] address review: move up type codes in table --- Doc/library/struct.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index 5e3cda6279c975..b14ca720af1d5f 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -260,16 +260,16 @@ platform-dependent. +--------+--------------------------+--------------------+----------------+------------+ | ``d`` | :c:expr:`double` | float | 8 | \(4) | +--------+--------------------------+--------------------+----------------+------------+ +| ``F`` | :c:expr:`float complex` | complex | 8 | \(10) | ++--------+--------------------------+--------------------+----------------+------------+ +| ``D`` | :c:expr:`double complex` | complex | 16 | \(10) | ++--------+--------------------------+--------------------+----------------+------------+ | ``s`` | :c:expr:`char[]` | bytes | | \(9) | +--------+--------------------------+--------------------+----------------+------------+ | ``p`` | :c:expr:`char[]` | bytes | | \(8) | +--------+--------------------------+--------------------+----------------+------------+ | ``P`` | :c:expr:`void \*` | integer | | \(5) | +--------+--------------------------+--------------------+----------------+------------+ -| ``F`` | :c:expr:`float complex` | complex | 8 | \(10) | -+--------+--------------------------+--------------------+----------------+------------+ -| ``D`` | :c:expr:`double complex` | complex | 16 | \(10) | -+--------+--------------------------+--------------------+----------------+------------+ .. versionchanged:: 3.3 Added support for the ``'n'`` and ``'N'`` formats. From e340cdf35df5545911083450ce5b73cafb075c57 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 24 Apr 2025 14:57:33 +0300 Subject: [PATCH 04/10] + remove have_c_complex checking in tests --- Lib/test/test_struct.py | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index a410fd5a1940d1..7df01f28f09118 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -22,12 +22,6 @@ INF = float('inf') NAN = float('nan') -try: - struct.pack('D', 1j) - have_c_complex = True -except struct.error: - have_c_complex = False - def iter_integer_formats(byteorders=byteorders): for code in integer_codes: for byteorder in byteorders: @@ -796,7 +790,6 @@ def test_repr(self): s = struct.Struct('=i2H') 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)] @@ -806,19 +799,6 @@ def test_c_complex_round_trip(self): 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 = "'F' format not supported on this system" - msg2 = "'D' format not supported on this system" - with self.assertRaisesRegex(struct.error, msg1): - struct.pack('F', 1j) - with self.assertRaisesRegex(struct.error, msg1): - struct.unpack('F', b'1') - with self.assertRaisesRegex(struct.error, msg2): - struct.pack('D', 1j) - with self.assertRaisesRegex(struct.error, msg2): - struct.unpack('D', b'1') - class UnpackIteratorTest(unittest.TestCase): """ From 78ce03ec155189004e70626f204ec72676b284ca Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Fri, 25 Apr 2025 11:05:35 +0300 Subject: [PATCH 05/10] Update Doc/whatsnew/3.14.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/whatsnew/3.14.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 11a7ac45de77fa..4edab5a78dc960 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -1173,7 +1173,8 @@ struct ------ * Support the :c:expr:`float complex` and :c:expr:`double complex` C types in - the :mod:`struct` module (formatting characters ``'F'`` and ``'D'``. + the :mod:`struct` module (formatting characters ``'F'`` and ``'D'`` + respectively). (Contributed by Sergey B Kirpichev in :gh:`121249`.) From 0efae27fb269c19994c18a5eac6f182b684f2935 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Fri, 25 Apr 2025 12:06:36 +0300 Subject: [PATCH 06/10] address review: adjust blurb entry --- Misc/NEWS.d/3.14.0a1.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS.d/3.14.0a1.rst b/Misc/NEWS.d/3.14.0a1.rst index 98639f0d3505d5..49b1392f13b115 100644 --- a/Misc/NEWS.d/3.14.0a1.rst +++ b/Misc/NEWS.d/3.14.0a1.rst @@ -2119,9 +2119,8 @@ imported. Patch by Sergey B Kirpichev. .. nonce: W9Gd09 .. section: Library -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. +Support the :c:expr:`float complex` and :c:expr:`double complex` C types in the +:mod:`struct` module. Patch by Sergey B Kirpichev. .. From c37724f489baea0775cc178df41925abe494269d Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Fri, 25 Apr 2025 16:20:51 +0300 Subject: [PATCH 07/10] + add new blurb entry --- Misc/NEWS.d/3.14.0a1.rst | 10 ---------- .../2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst | 2 ++ 2 files changed, 2 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst diff --git a/Misc/NEWS.d/3.14.0a1.rst b/Misc/NEWS.d/3.14.0a1.rst index 49b1392f13b115..f64efff7aa4cd1 100644 --- a/Misc/NEWS.d/3.14.0a1.rst +++ b/Misc/NEWS.d/3.14.0a1.rst @@ -2114,16 +2114,6 @@ imported. Patch by Sergey B Kirpichev. .. -.. date: 2024-07-10-08-13-34 -.. gh-issue: 121249 -.. nonce: W9Gd09 -.. section: Library - -Support the :c:expr:`float complex` and :c:expr:`double complex` C types in the -:mod:`struct` module. Patch by Sergey B Kirpichev. - -.. - .. date: 2024-07-09-12-23-32 .. gh-issue: 121486 .. nonce: Iultjh diff --git a/Misc/NEWS.d/next/Library/2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst b/Misc/NEWS.d/next/Library/2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst new file mode 100644 index 00000000000000..52b12083748fc3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst @@ -0,0 +1,2 @@ +Support the :c:expr:`float complex` and :c:expr:`double complex` C types in +the :mod:`struct` module. Patch by Sergey B Kirpichev. From 38fa2a73f72d03e3dd49098e56f1d0dd870444e1 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Fri, 25 Apr 2025 18:13:59 +0300 Subject: [PATCH 08/10] restore Misc/NEWS.d/3.14.0a1.rst --- Misc/NEWS.d/3.14.0a1.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Misc/NEWS.d/3.14.0a1.rst b/Misc/NEWS.d/3.14.0a1.rst index f64efff7aa4cd1..98639f0d3505d5 100644 --- a/Misc/NEWS.d/3.14.0a1.rst +++ b/Misc/NEWS.d/3.14.0a1.rst @@ -2114,6 +2114,17 @@ imported. Patch by Sergey B Kirpichev. .. +.. date: 2024-07-10-08-13-34 +.. gh-issue: 121249 +.. nonce: W9Gd09 +.. section: Library + +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. + +.. + .. date: 2024-07-09-12-23-32 .. gh-issue: 121486 .. nonce: Iultjh From 70a3c6b95baf6e21d07446f79ff7dc36dad10663 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Fri, 2 May 2025 16:45:49 +0300 Subject: [PATCH 09/10] Update Misc/NEWS.d/next/Library/2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst --- .../next/Library/2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst b/Misc/NEWS.d/next/Library/2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst index 52b12083748fc3..28140ab30544b2 100644 --- a/Misc/NEWS.d/next/Library/2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst +++ b/Misc/NEWS.d/next/Library/2025-04-25-16-20-49.gh-issue-121249.uue2nK.rst @@ -1,2 +1,2 @@ -Support the :c:expr:`float complex` and :c:expr:`double complex` C types in +Always support the :c:expr:`float complex` and :c:expr:`double complex` C types in the :mod:`struct` module. Patch by Sergey B Kirpichev. From 83467158d01a5b904fb7a988225ce3766251122c Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Fri, 2 May 2025 16:48:08 +0300 Subject: [PATCH 10/10] Update Doc/library/struct.rst --- Doc/library/struct.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index b14ca720af1d5f..66a1fdea54d857 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -360,11 +360,10 @@ Notes: 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. - Note that support for complex types is available unconditionally, - regardless on support IEC 60559 compatible complex arithmetic (Annex G of - the C11 standard) by the compiler. Each complex type is interpreted as an - array type containing exactly two elements of the corresponding real type - (real and imaginary parts, respectively). + Note that complex types (``F`` and ``D``) are available unconditionally, + despite complex types being an optional feature in C. + As specified in the C11 standard, each complex type is represented by a + two-element C array containing, respectively, the real and imaginary parts. A format character may be preceded by an integral repeat count. For example,