python_util.h

Defines

PyLong_SetSignAndDigitCount(obj, is_neg, size)
GET_OB_DIGIT(obj)
PyLong_IsNegative(obj)
PyLong_DigitCount(obj)
WHOLE_BYTES
REMAINING_BITS
REMAINING_BITS_MASK

Functions

static inline PyLongObject *PyLong_New(std::size_t python_digits)

Creation of a new PyLongObject that can be returned to Python

static inline bool python_long_is_negative(const nanobind::int_ &py_long_int)

Test if Python long integer (nb::int_) is negative

static std::vector<apy_limb_t> limb_vec_from_py_long_vec(const std::size_t count, const PyLongObject *py_long)

Convert Python limbs (of length PYLONG_BITS_IN_DIGIT) to apy_type_t limbs (of length APY_LIMB_SIZE_BITS).

static inline std::vector<apy_limb_t> python_long_to_limb_vec(const nanobind::int_ &py_long_int, std::optional<std::size_t> n_min_limbs = std::nullopt)

Python arbitrary long integer object to apy_limb_t vector. If n_min_limbs is set, at least that many limbs will be available in the result.

template<class RANDOM_ACCESS_ITERATOR>
static inline nanobind::int_ python_limb_vec_to_long(RANDOM_ACCESS_ITERATOR begin, RANDOM_ACCESS_ITERATOR end, bool vec_is_signed = false, std::optional<unsigned> bits_last_limb = std::nullopt)

Convert a limb vector (std::vector<apy_limb_t>) to a Python long integer object wrapped in a nanobind::int_.

template<typename ...PyTypes>
static inline bool is_seq_and_exclude(const nanobind::handle &obj)

Test whether a nb::object is a Python sequence, and simultaneously that the object is not any of the PyArgs types.

static inline std::vector<std::size_t> _python_sequence_extract_shape_recursive_descent(const nanobind::sequence &sequence, std::string_view err_prefix)

Retrieve the sequence of a python sequence object through recursive descent along the dimensions.

template<bool IS_COMPLEX_COLLAPSE = false>
static inline std::vector<std::size_t> python_sequence_extract_shape(const nanobind::sequence &seq, std::string_view err_prefix)

Retrieve the shape of a possibly nested Python sequence of iterable object. When IS_COMPLEX_COLLAPSE is true, the last dimension is truncated if it is exactly equal to two.

template<typename ...PyTypes>
static std::vector<nanobind::object> python_sequence_walk(const nanobind::sequence &py_seq, std::string_view err_prefix)

Walk a, possibly nested, Python sequence of iterable objects and convert every Python object (of type <T>, via nb::cast<T>()) and return them in a std::vector<T>. The sequence is walked in a depth-first search manner. If any object in the sequence bit_pattern_sequence does not match <T> or another Python sequence a std::domain_error exception is raised.