2015-07-30 13:29:00 +00:00
|
|
|
/*
|
2015-10-15 16:13:33 +00:00
|
|
|
pybind11/complex.h: Complex number support
|
2015-07-30 13:29:00 +00:00
|
|
|
|
2016-04-17 18:21:41 +00:00
|
|
|
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
2015-07-30 13:29:00 +00:00
|
|
|
|
|
|
|
All rights reserved. Use of this source code is governed by a
|
|
|
|
BSD-style license that can be found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2015-10-15 16:13:33 +00:00
|
|
|
#include "pybind11.h"
|
2022-02-10 20:17:07 +00:00
|
|
|
|
2015-07-30 13:29:00 +00:00
|
|
|
#include <complex>
|
|
|
|
|
2016-01-21 16:42:46 +00:00
|
|
|
/// glibc defines I as a macro which breaks things, e.g., boost template names
|
|
|
|
#ifdef I
|
2022-02-10 20:17:07 +00:00
|
|
|
# undef I
|
2016-01-21 16:42:46 +00:00
|
|
|
#endif
|
|
|
|
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
2017-05-10 09:36:24 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
struct format_descriptor<std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>> {
|
2017-05-10 09:36:24 +00:00
|
|
|
static constexpr const char c = format_descriptor<T>::c;
|
2022-02-10 20:17:07 +00:00
|
|
|
static constexpr const char value[3] = {'Z', c, '\0'};
|
2017-05-10 09:36:24 +00:00
|
|
|
static std::string format() { return std::string(value); }
|
|
|
|
};
|
|
|
|
|
2017-11-20 13:19:53 +00:00
|
|
|
#ifndef PYBIND11_CPP17
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
constexpr const char
|
|
|
|
format_descriptor<std::complex<T>,
|
|
|
|
detail::enable_if_t<std::is_floating_point<T>::value>>::value[3];
|
2017-05-10 09:36:24 +00:00
|
|
|
|
2017-11-20 13:19:53 +00:00
|
|
|
#endif
|
|
|
|
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
2015-07-30 13:29:00 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
struct is_fmt_numeric<std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>> {
|
Numpy: better compilation errors, long double support (#619)
* Clarify PYBIND11_NUMPY_DTYPE documentation
The current documentation and example reads as though
PYBIND11_NUMPY_DTYPE is a declarative macro along the same lines as
PYBIND11_DECLARE_HOLDER_TYPE, but it isn't. The changes the
documentation and docs example to make it clear that you need to "call"
the macro.
* Add satisfies_{all,any,none}_of<T, Preds>
`satisfies_all_of<T, Pred1, Pred2, Pred3>` is a nice legibility-enhanced
shortcut for `is_all<Pred1<T>, Pred2<T>, Pred3<T>>`.
* Give better error message for non-POD dtype attempts
If you try to use a non-POD data type, you get difficult-to-interpret
compilation errors (about ::name() not being a member of an internal
pybind11 struct, among others), for which isn't at all obvious what the
problem is.
This adds a static_assert for such cases.
It also changes the base case from an empty struct to the is_pod_struct
case by no longer using `enable_if<is_pod_struct>` but instead using a
static_assert: thus specializations avoid the base class, POD types
work, and non-POD types (and unimplemented POD types like std::array)
get a more informative static_assert failure.
* Prefix macros with PYBIND11_
numpy.h uses unprefixed macros, which seems undesirable. This prefixes
them with PYBIND11_ to match all the other macros in numpy.h (and
elsewhere).
* Add long double support
This adds long double and std::complex<long double> support for numpy
arrays.
This allows some simplification of the code used to generate format
descriptors; the new code uses fewer macros, instead putting the code as
different templated options; the template conditions end up simpler with
this because we are now supporting all basic C++ arithmetic types (and
so can use is_arithmetic instead of is_integral + multiple
different specializations).
In addition to testing that it is indeed working in the test script, it
also adds various offset and size calculations there, which
fixes the test failures under x86 compilations.
2017-01-31 16:00:15 +00:00
|
|
|
static constexpr bool value = true;
|
|
|
|
static constexpr int index = is_fmt_numeric<T>::index + 3;
|
|
|
|
};
|
2015-07-30 13:29:00 +00:00
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
template <typename T>
|
|
|
|
class type_caster<std::complex<T>> {
|
2015-07-30 13:29:00 +00:00
|
|
|
public:
|
2017-02-04 01:16:14 +00:00
|
|
|
bool load(handle src, bool convert) {
|
2022-02-08 00:23:20 +00:00
|
|
|
if (!src) {
|
2016-05-10 14:59:01 +00:00
|
|
|
return false;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
|
|
|
if (!convert && !PyComplex_Check(src.ptr())) {
|
2017-02-04 01:16:14 +00:00
|
|
|
return false;
|
2022-02-08 00:23:20 +00:00
|
|
|
}
|
2016-01-17 21:36:44 +00:00
|
|
|
Py_complex result = PyComplex_AsCComplex(src.ptr());
|
2015-07-30 13:29:00 +00:00
|
|
|
if (result.real == -1.0 && PyErr_Occurred()) {
|
|
|
|
PyErr_Clear();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
value = std::complex<T>((T) result.real, (T) result.imag);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-02-10 20:17:07 +00:00
|
|
|
static handle
|
|
|
|
cast(const std::complex<T> &src, return_value_policy /* policy */, handle /* parent */) {
|
2015-07-30 13:29:00 +00:00
|
|
|
return PyComplex_FromDoubles((double) src.real(), (double) src.imag());
|
|
|
|
}
|
|
|
|
|
2021-12-21 19:24:21 +00:00
|
|
|
PYBIND11_TYPE_CASTER(std::complex<T>, const_name("complex"));
|
2015-07-30 13:29:00 +00:00
|
|
|
};
|
2020-07-08 22:14:41 +00:00
|
|
|
PYBIND11_NAMESPACE_END(detail)
|
|
|
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|