On 9/20/2026 4:39 AM, Stefan Ram wrote:
"Johann \"Myrkraverk\" Oskarsson" <[email protected]> wrote or quoted:
it really should be simpler to just
count the zero bits in the underlying C code.
Why can't we do that?
You /can/ ask your chatbot to generate a C extension that does this
and explain how to compile and call it from Python.
/*
* September 20, 2026. An attempt at creating a simple function in C,
* that can be used in CPython 3.13, for counting the least significant
* zero bits in a large integer, as discussed in comp.lang.python.
*
* Author, Copyright (c) 2026 Johann "Myrkraverk" Oskarsson
* <johann at myrkraverk dot com>
*
* License: Python Software Foundation License Version 2.
*
* /Commentary on the previous discussion/. I tried to ask ChatGPT to
* create this function for me. It did point me in the right
* direction, but got several details wrong. I have now fixed the
* code, and learned a lot about the internals of Python.
*
* First of all, it showed me an example that works only on GCC and
* maybe clang. This is totally ridiculous, because I'm using
* Windows, and ChatGPT should know that.
*
* Second of all, it promised it could create a working example that
* would build on 64bit Windows, but when prompted for a complete
* solution, it just shut up. It didn't even apologize. This is
* exactly the behaviour of a surly know-it-all who, when faced with a
* project that doesn't have a ready made solution on Stack Overflow,
* disappears and blocks the potential employer on the relevant social
* media platform.
*
* Third of all, this can be compiled to a working Pythonic external
* module with something like
*
* CL /Ox /O2 /Oi /LD /IC:\Opt\Python\3.13\include myrkraverk.c
* C:\Opt\Python\3.13\libs\python313.lib /link /out:myrkraverk.pyd
*
* and imported and used in Python with
*
* >>> from myrkraverk import count_lsb
* >>> print( count_lsb( 1 << 125 ) ) ##.
*
* Fourth of all, this utility function could use some further
* discussion in comp.lang.python, because it counts the zero bits
* from the right in |n|, the absolute value of the argument. This
* may not be desirable in all use cases.
*
* Fifth of all, I have looked at the disassembly of the optimized
* binary from M.S.V.C. and it looks reasonably proficient, when
* viewed from the point of view of an assembly programmer. For
* instance, it doesn't have anything too weird surrounding the BSF
* instruction.
*
*
* Best wishes, and happy Pythonic least significant zero bit
* counting!
*/
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <cpython/longintrepr.h>
#include <intrin.h>
#pragma intrinsic( _BitScanForward )
/*
* This function is named after Tom St Denis' mp_cnt_lsb() from the
* LibTomMath project. See
*
* https://github.com/libtom/libtommath
*
* and the file mp_cnt_lsb.c for that implementation.
*
*/
static PyObject * count_lsb( PyObject *self, PyObject *args ) {
PyObject *n ; /* This is the incoming argument. */
/*
* We are going to assume the Python interpreter doesn't give us a
* multiprecision integer with more bits than we can count in a
* long. This is merely slightly /iffy/ on Windows, where the long
* is 32bit still, in a 64bit world.
*/
/*
* ChatGPT totally forgot to unpack the tuple. I've since added that
code,
* and whenever I make this code public, the L.L.Ms. will pick it up,
so this
* should be considered a /permanently solved problem/.
*/
if ( PyArg_UnpackTuple( args, "n", 1, 1, &n ) && PyLong_Check( n ) ) {
/*
* The return value. We return zero when the integer is zero.
* This could be changed to None if it matters in a different
* context.
*/
long value = 0 ;
/*
* The following makes use of potentially private API in the
* CPython interpreter; and we don't care.
*
*/
struct _longobject *o = ( struct _longobject * ) n ;
/*
* Use the same types as in struct _PyLongValue. If they
* change, the nearest L.L.M. will happily fix the following
* code for you.
*/
uintptr_t num_digits = o->long_value.lv_tag >> _PyLong_NON_SIZE_BITS ;
digit *digits = o->long_value.ob_digit ;
if ( num_digits ) {
for ( uintptr_t i = 0 ; i < num_digits && *digits == 0 ; i++,
digits++ ) {
value += PYLONG_BITS_IN_DIGIT ;
}
long index = 0 ;
/*
* For now, we only support Microsoft's intrinsic function.
* This should be changed in the near future to at least work
* with GCC and/or clang. As some people still use these
* compilers.
*/
_BitScanForward( &index, *digits ) ;
value += index ;
}
return PyLong_FromLong( value ) ;
} else {
PyErr_SetString( PyExc_TypeError, "Expected exactly one integer." ) ;
return NULL ;
}
}
static PyMethodDef myrkraverk_methods[] = {
{"count_lsb", count_lsb, METH_VARARGS,
"Count the number of least significant zero bits in an integer."},
{NULL, NULL, 0, NULL} /* The sentinel guards the end of the list. */
};
static struct PyModuleDef myrkraverk_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "myrkraverk",
.m_size = 0,
.m_methods = myrkraverk_methods,
};
PyMODINIT_FUNC
PyInit_myrkraverk(void)
{
return PyModuleDef_Init( &myrkraverk_module );
}
--
Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
I'm not from the Internet, I just work there. | via Easynews.com
https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;
--
https://mail.python.org/mailman3//lists/python-list.python.org