8000 Expose inline versions of _PyLong_IsCompact & _PyLong_CompactValue by encukou · Pull Request #16 · faster-cpython/cpython · GitHub
[go: up one dir, main page]

Skip to content

Expose inline versions of _PyLong 8000 _IsCompact & _PyLong_CompactValue #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Expose inline versions of _PyLong_IsCompact & _PyLong_CompactValue in…
… unstable API.
  • Loading branch information
encukou committed May 15, 2023
commit 3d43ba5836fded6a136752472fa1127d63fe5909
26 changes: 26 additions & 0 deletions Include/cpython/longintrepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,32 @@ PyAPI_FUNC(PyLongObject *)
_PyLong_FromDigits(int negative, Py_ssize_t digit_count, digit *digits);


/* Inline some internals for speed. These should be in pycore_long.h
* if user code didn't need them inlined. */

#define _PyLong_SIGN_MASK 3
#define _PyLong_NON_SIZE_BITS 3

static inline int
_PyLong_IsCompact(const PyLongObject* op) {
assert(PyLong_Check(op));
return op->long_value.lv_tag < (2 << _PyLong_NON_SIZE_BITS);
}

#define PyUnstable_Int_IsCompact _PyLong_IsCompact

static inline Py_ssize_t
_PyLong_CompactValue(const PyLongObject *op)
{
assert(PyLong_Check(op));
assert(PyUnstable_Int_IsCompact(op));
Py_ssize_t sign = 1 - (op->long_value.lv_tag & _PyLong_SIGN_MASK);
return sign * (Py_ssize_t)op->long_value.ob_digit[0];
}

#define PyUnstable_Int_CompactValue _PyLong_CompactValue


#ifdef __cplusplus
}
#endif
Expand Down
39 changes: 15 additions & 24 deletions Include/internal/pycore_long.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,21 @@ PyAPI_FUNC(char*) _PyLong_FormatBytesWriter(
#define SIGN_NEGATIVE 2
#define NON_SIZE_BITS 3

/* The functions _PyLong_IsCompact and _PyLong_CompactValue are defined
* in Include/cpython/longobject.h, since they need to be inline.
*
* "Compact" values have at least one bit to spare,
* so that addition and subtraction can be performed on the values
* without risk of overflow.
*
* The inline functions need tag bits.
* For readability, rather than do `#define SIGN_MASK _PyLong_SIGN_MASK`
* we define them to the numbers in both places and then assert that
* they're the same.
*/
static_assert(SIGN_MASK == _PyLong_SIGN_MASK);
static_assert(NON_SIZE_BITS == _PyLong_NON_SIZE_BITS);

/* All *compact" values are guaranteed to fit into
* a Py_ssize_t with at least one bit to spare.
* In other words, for 64 bit machines, compact
Expand All @@ -131,13 +146,6 @@ _PyLong_IsNonNegativeCompact(const PyLongObject* op) {
return op->long_value.lv_tag <= (1 << NON_SIZE_BITS);
}

static inline int
_PyLong_IsCompact(const PyLongObject* op) {
assert(PyLong_Check(op));
return op->long_value.lv_tag < (2 << NON_SIZE_BITS);
}

#define PyUnstable_Int_IsCompact _PyLong_IsCompact

static inline int
_PyLong_BothAreCompact(const PyLongObject* a, const PyLongObject* b) {
Expand All @@ -146,23 +154,6 @@ _PyLong_BothAreCompact(const PyLongObject* a, const PyLongObject* b) {
return (a->long_value.lv_tag | b->long_value.lv_tag) < (2 << NON_SIZE_BITS);
}

/* Returns a *compact* value, iff `_PyLong_IsCompact` is true for `op`.
*
* "Compact" values have at least one bit to spare,
* so that addition and subtraction can be performed on the values
* without risk of overflow.
*/
static inline Py_ssize_t
_PyLong_CompactValue(const PyLongObject *op)
{
assert(PyLong_Check(op));
assert(_PyLong_IsCompact(op));
Py_ssize_t sign = 1 - (op->long_value.lv_tag & SIGN_MASK);
return sign * (Py_ssize_t)op->long_value.ob_digit[0];
}

#define PyUnstable_Int_CompactValue _PyLong_CompactValue

static inline bool
_PyLong_IsZero(const PyLongObject *op)
{
Expand Down
0