apytypes_util.h

Defines

UINT64_TO_LIMB(x)
CREATE_FUNCTOR_FROM_FUNC(FUNCTOR_NAME, FUNC_NAME)

Macro for creating a void-specialization state-less functor FUNCTOR_NAME from a function FUNC_NAME. The void-specialization functor allows template argument deduction to be performed once its function is called. Neat!

Functions

static inline void apytypes_unreachable()

Mark code path unreachable. Allows the compiler to make further control-flow optimizations. Calling this function under any circumstance is undefined behaviour.

static inline std::tuple<apy_limb_t, apy_limb_t> long_mult(apy_limb_t src0, apy_limb_t src1)

Compute multiplication between two apy_limb_t and obtain double length result.

template<typename INT_TYPE>
static inline std::size_t trailing_zeros(INT_TYPE n)

Compute the number of trailing zeros in an integer.

template<typename INT_TYPE>
static inline std::size_t leading_zeros(INT_TYPE n)

Compute the number of leading zeros in an integer.

template<typename INT_TYPE>
static inline std::size_t leading_ones(INT_TYPE n)

Compute number of leading ones in an integer.

template<typename INT_TYPE>
static inline std::size_t bit_width(INT_TYPE n)

Compute bit-width (ceil(log2(1 + n)) for unsigned n) of an integer n.

template<typename INT_TYPE>
static inline std::size_t count_trailing_bits(INT_TYPE n)

Compute number of trailing bits after most significant 1 in an integer.

static inline std::size_t bits_to_limbs(std::size_t bits)

Quickly evaluate how many limbs are required to to store a bits bit word. Undefined behaviour when bits is equal to zero.

template<class RANDOM_ACCESS_ITERATOR>
static inline std::size_t significant_limbs(RANDOM_ACCESS_ITERATOR begin, RANDOM_ACCESS_ITERATOR end)

Count the number of significant limbs in unsigned limb vector.

template<class RANDOM_ACCESS_ITERATOR>
static inline std::size_t limb_vector_leading_zeros(RANDOM_ACCESS_ITERATOR begin, RANDOM_ACCESS_ITERATOR end)

Return the number of leading zeros of a limb vector.

template<class RANDOM_ACCESS_ITERATOR>
static inline std::size_t limb_vector_leading_ones(RANDOM_ACCESS_ITERATOR begin, RANDOM_ACCESS_ITERATOR end)

Return the number of leading signs of a limb vector, minus one.

template<typename INT_TYPE>
static inline std::size_t nibble_width(INT_TYPE x)

Quickly count the number of nibbles in an unsigned apy_limb_t

static inline std::vector<std::uint8_t> to_nibble_list(const std::vector<apy_limb_t> &data_array, std::size_t len = 0)

Convert a positive arbitrary size integer array (std::vector<apy_limb_t>) to a nibble list. The nibble list contains least significant nibble first. Argument len indicates the intended bcd length of the output. When set, no more than result.rend() - len zeros will be removed.

static inline std::vector<apy_limb_t> from_nibble_list(const std::vector<std::uint8_t> &nibble_list)

Convert a nibble list into a positive integer array (std::vector<apy_limb_t>). The nibble list is assumed to have least significant nibble first.

static inline std::vector<apy_limb_t> double_dabble(std::vector<apy_limb_t> nibble_data)

Double-dabble algorithm for binary->BCD conversion.

static inline std::string bcds_to_string(const std::vector<apy_limb_t> bcds)

Convert a BCD limb vector into a std::string.

static inline std::vector<apy_limb_t> reverse_double_dabble(const std::vector<std::uint8_t> &bcd_list)

Reverse double-dabble algorithm for BCD->binary conversion.

static inline void bcd_limb_vec_div2(std::vector<apy_limb_t> &bcd_list)

Divide the number in a BCD limb vector by two.

static inline void bcd_limb_vec_mul2(std::vector<apy_limb_t> &bcd_list)

Multiply the number in a BCD limb vector by two.

static inline void bcd_mul2(std::vector<std::uint8_t> &bcd_list)

Multiply BCD vector (std::vector<std::uint8_t>) by two. The first element (front()) in the vector is considered LSB.

static inline std::string string_trim_leading_whitespace(const std::string &str)

Trim a string from leading whitespace.

static inline std::string string_trim_trailing_whitespace(const std::string &str)

Trim a string from trailing whitespace.

static inline std::string string_trim_whitespace(const std::string &str)

Trim a string from leading and trailing whitespace.

static inline bool is_valid_decimal_numeric_string(const std::string &str)

Test if a string is a valid numeric decimal string.

static inline std::string string_trim_zeros(const std::string &str)

Trim a string from unnecessary leading and trailing zeros, that don’t affect numeric value of the string. This function also attaches a zero to the string if it starts with a decimal dot, and it removes the decimal dot if no digit after it affects its value (e.g., 0.00 == 0).

template<class RANDOM_ACCESS_ITERATOR>
static inline void limb_vector_asr(RANDOM_ACCESS_ITERATOR it_begin, RANDOM_ACCESS_ITERATOR it_end, unsigned shift_amnt)

Perform arithmetic right shift on a limb vector.

template<class RANDOM_ACCESS_ITERATOR>
static inline void limb_vector_lsr(RANDOM_ACCESS_ITERATOR it_begin, RANDOM_ACCESS_ITERATOR it_end, unsigned shift_amnt)

Perform logical right shift on a limb vector.

template<class RANDOM_ACCESS_ITERATOR>
static inline void limb_vector_lsl_inner(RANDOM_ACCESS_ITERATOR it_begin, RANDOM_ACCESS_ITERATOR it_end, unsigned int limb_skip, unsigned int limb_shift, unsigned int vec_size)

Perform logical left shift on a limb vector.

template<class RANDOM_ACCESS_ITERATOR>
static inline void limb_vector_lsl(RANDOM_ACCESS_ITERATOR it_begin, RANDOM_ACCESS_ITERATOR it_end, unsigned shift_amnt)

Perform logical left shift on a limb vector.

template<class RANDOM_ACCESS_ITERATOR>
static inline bool limb_vector_gte_pow2(RANDOM_ACCESS_ITERATOR it_begin, RANDOM_ACCESS_ITERATOR it_end, unsigned n)

Test if positive integer value in limb vector is greater than or equal to a non-negative power-of-two (>= 2 ^ n for unsigned n)

template<class RANDOM_ACCESS_ITERATOR1, class RANDOM_ACCESS_ITERATOR2>
static inline bool limb_vector_signed_less_than(RANDOM_ACCESS_ITERATOR1 src1, RANDOM_ACCESS_ITERATOR2 src2, std::size_t limbs)

Test if the (two’s complement) value of src1 is smaller than that of src2

template<class RANDOM_ACCESS_ITERATOR>
static inline apy_limb_t limb_vector_add_pow2(RANDOM_ACCESS_ITERATOR it_begin, RANDOM_ACCESS_ITERATOR it_end, unsigned n)

Add a power-of-two (2 ^ n) onto a limb vector. Return carry out.

template<class RANDOM_ACCESS_ITERATOR>
static inline apy_limb_t limb_vector_sub_pow2(RANDOM_ACCESS_ITERATOR it_begin, RANDOM_ACCESS_ITERATOR it_end, unsigned n)

Subtract a power-of-two (2 ^ n) from a limb vector. Return borrow.

static inline int bits_from_optional(std::optional<int> bits, std::optional<int> int_bits, std::optional<int> frac_bits)

Return the bits specifier from user provided optional bit specifiers. Throws nb::value_error if the resulting number of bits is less than or equal to zero, or if not exactly two of three bit specifiers are set.

static inline std::tuple<int, int> bits_from_optional_cast(std::optional<int> bits, std::optional<int> int_bits, std::optional<int> frac_bits, int current_bits, int current_int_bits)

Return a two-tuple of ints (bits, int_bits) for a set of optional bit-specifiers used in the casting context. Throws nanobind::value_error if parameters do not add up, or if resulting bits is smaller than or equal to zero.

template<class RANDOM_ACCESS_ITERATOR>
static inline bool limb_vector_is_negative(RANDOM_ACCESS_ITERATOR cbegin_it, RANDOM_ACCESS_ITERATOR cend_it)

Test if two’s complement value in a limb vector is negative.

template<class RANDOM_ACCESS_ITERATOR>
static inline bool limb_vector_is_zero(RANDOM_ACCESS_ITERATOR cbegin_it, RANDOM_ACCESS_ITERATOR cend_it)

Test if the stored value of a limb vector is zero (all limbs are zero)

template<class RANDOM_ACCESS_ITERATOR>
static inline bool limb_vector_or_reduce(RANDOM_ACCESS_ITERATOR cbegin_it, RANDOM_ACCESS_ITERATOR cend_it, unsigned n)

Reduce the first n bits in a limb vector over bitwise or. Return bool. Unconditionally Return false when n == 0. Undefined behaviour if n is greater than the number of bits in the limb vector.

template<class RANDOM_ACCESS_ITERATOR>
static inline bool limb_vector_test_bit(RANDOM_ACCESS_ITERATOR cbegin_it, RANDOM_ACCESS_ITERATOR cend_it, unsigned n)

Test if the n -th bit (zero indexed) is set in a limb vector. Undefined behaviour if bit n is located outside the limb vector.

template<class RANDOM_ACCESS_ITERATOR>
static inline void limb_vector_set_bit(RANDOM_ACCESS_ITERATOR begin_it, RANDOM_ACCESS_ITERATOR end_it, unsigned n, bool bit)

Set the n -th bit (zero indexed) of a limb vector to bit. Undefined behaviour if bit n is located outside the limb vector.

template<class RANDOM_ACCESS_ITERATOR_IN, class RANDOM_ACCESS_ITERATOR_OUT>
static inline apy_limb_t limb_vector_negate(RANDOM_ACCESS_ITERATOR_IN cbegin_it, RANDOM_ACCESS_ITERATOR_IN cend_it, RANDOM_ACCESS_ITERATOR_OUT res_it)

Take the two’s complement negative value of a limb vector and place onto res_out

template<class RANDOM_ACCESS_ITERATOR_IN>
static inline apy_limb_t limb_vector_negate_inplace(RANDOM_ACCESS_ITERATOR_IN cbegin_it, RANDOM_ACCESS_ITERATOR_IN cend_it)

Take the two’s complement negative value of a limb vector inplace.

template<class RANDOM_ACCESS_ITERATOR_IN, class RANDOM_ACCESS_ITERATOR_OUT>
static inline bool limb_vector_abs(RANDOM_ACCESS_ITERATOR_IN cbegin_it, RANDOM_ACCESS_ITERATOR_IN cend_it, RANDOM_ACCESS_ITERATOR_OUT res_it)

Take the two’s complement absolute value of a limb vector and place onto res_out. Return true if the argument is negative

template<class RANDOM_ACCESS_ITERATOR>
static inline bool limb_vector_all_zeros(RANDOM_ACCESS_ITERATOR cbegin_it, RANDOM_ACCESS_ITERATOR cend_it, unsigned n = 0)

Test if the bits in a limb vector are all zeros starting from bit n (zero indexed). Bit n is assumed to be located in the first limb.

template<class RANDOM_ACCESS_ITERATOR>
static inline bool limb_vector_all_ones(RANDOM_ACCESS_ITERATOR cbegin_it, RANDOM_ACCESS_ITERATOR cend_it, unsigned n = 0)

Test if the bits in a limb vector are all ones starting from bit n (zero indexed). Bit n is assumed to be located in the first limb.

template<typename RANDOM_ACCESS_ITERATOR_IN, typename RANDOM_ACCESS_ITERATOR_OUT>
static inline void limb_vector_copy_sign_extend(RANDOM_ACCESS_ITERATOR_IN src_begin, RANDOM_ACCESS_ITERATOR_IN src_end, RANDOM_ACCESS_ITERATOR_OUT dst_begin, RANDOM_ACCESS_ITERATOR_OUT dst_end)

Copy limbs from src to dst and possibly sign extend the data in dst

template<typename VECTOR_TYPE>
static inline uint64_t uint64_t_from_limb_vector(const VECTOR_TYPE &limb_vec, std::size_t n)

Read an unsigned 64-bit value from a limb vector. If APY_LIMB_SIZE_BITS == 64, this results in a normal vector read without bounds checking. If APY_LIMB_SIZE_BITS == 32, the second 32-bits limb is bound-checked and the result upper 32-bits are zeroed if out-of-bounds.

template<typename T>
std::string tuple_string_from_vec(const std::vector<T> &vec)

Construct a Python tuple-literal-string from a vector of T. The type T must be convertible to string through both a std::stringstream and fmt::format({}).

static inline apy_limb_t twos_complement_overflow(apy_limb_t value, int bits)
static inline std::size_t fold_shape(std::vector<std::size_t>::const_iterator cbegin, std::vector<std::size_t>::const_iterator cend)

Fold a shape under multiplication.

static inline std::size_t fold_shape(const std::vector<std::size_t> &shape)

Fold a shape under multiplication.

static inline std::vector<std::size_t> strides_from_shape(const std::vector<std::size_t> &shape, std::size_t acc_base = 1)

Compute the strides from a shape.

template<typename RANDOM_ACCESS_ITERATOR_INOUT>
static inline void multi_limb_swap(RANDOM_ACCESS_ITERATOR_INOUT a_it, RANDOM_ACCESS_ITERATOR_INOUT b_it, std::size_t itemsize)

In-place multi-limb swap function.

template<typename RANDOM_ACCESS_ITERATOR_INOUT>
static inline void multi_limb_reverse(RANDOM_ACCESS_ITERATOR_INOUT begin_it, RANDOM_ACCESS_ITERATOR_INOUT end_it, std::size_t itemsize)

In-place multi-limb reverse function.

template<typename INT_TYPE = std::size_t, bool allow_negative_dimensions = false>
static inline std::vector<INT_TYPE> cpp_shape_from_python_shape_like(const std::variant<nanobind::tuple, nanobind::int_> &shape)

Create a C++ shape vector (std::vector<INT_TYPE>) from a Python shape object (std::variant<nanobind::tuple, nanobind::int_>).

static inline std::vector<std::size_t> cpp_axes_from_python(const std::optional<std::variant<nanobind::tuple, nanobind::int_>> &python_axes, std::size_t ndim)

Convert a Python tuple to a unique sorted list of dimensions (smaller than ndim)

template<typename APY_ARRAY>
static inline std::tuple<std::size_t, std::size_t, std::size_t> get_conv_lengths(const std::string &mode, const APY_ARRAY &a, const APY_ARRAY &b)

Get the convolutional properties len, n_left, and n_right (in that order) from a string of either “full”, “same”, or “valid”. Throws a nanobind::value_error if the string is anything else.

CREATE_FUNCTOR_FROM_FUNC(apy_add_n_functor, apy_addition_same_length)
CREATE_FUNCTOR_FROM_FUNC(apy_sub_n_functor, apy_subtraction_same_length)
class NotImplementedException : public std::domain_error

Public Functions

inline NotImplementedException(std::optional<std::string> msg = std::nullopt)
struct DoubleDabbleList
#include <apytypes_util.h>

Double-Dabble helper class with proporate methods for performing the double-dabble and reverse double-dabble algorithm.

Public Functions

inline void do_double(apy_limb_t new_bit)

Do one iteration of double (double-dabble)

inline void do_dabble()

Do one iteration of dabble (double-dabble)

inline void do_reverse_double(apy_limb_t &limb_out)

Do one iteration of reverse double (reverse double-dabble)

inline void do_reverse_dabble()

Do one iteration of reverse dabble (reverse double-dabble)

Public Members

std::vector<apy_limb_t> data = {0}

Public Static Attributes

static constexpr apy_limb_t _NIBBLE_MASK = APY_LIMB_SIZE_BITS == 64 ? 0x1111111111111111 : 0x11111111

Mask with a bit in every position where a nibble starts.