• Re: myrkraverk.c

    From Johann "Myrkraverk" Oskarsson@3:633/10 to All on Sun Sep 20 21:33:17 2026
    On 9/20/2026 8:25 PM, Stefan Ram wrote:
    "Johann \"Myrkraverk\" Oskarsson" <johann@myrkraverk.invalid> wrote or quoted:
    _BitScanForward( &index, *digits ) ;

    From the documentation:

    |If no bit is found, the function returns 0 and the value
    |written to the address in the first parameter is undefined.

    . However, if there are 32 0s before a 1 is found, this
    might be intended to add "32" to the total zero count.

    (GCC's and Clang's "__builtin_ctz" can also count bits and
    might be more portable.)

    Newsgroups: comp.lang.python,comp.lang.c,sci.math
    Followup-To: comp.lang.python,comp.lang.c

    Dear Stefan,

    You don't need to worry about _BitScanForward(). By the time that
    function call happens, we are fairly certain there is a bit to find.
    This is because we have already looped past all the zero digits [1],
    and assume a real integer given to us from the outer Python runtime en- vironment is not zero. Otherwise, we simply assume the CPython runtime
    to be buggy, and don't care about any of the results.

    Perhaps I should have made that clearer in the code comments?

    A bit more worrying is that I do not off hand know how to time my cre-
    ation. This is because /timeit/ can't find it. I do not know why, and hopefully the wizards of comp.lang.python can help benchmark this func-
    tion against ( n & -n ).bit_length() - 1 # for some really long int-
    egers.

    See for instance this session in my recent history.

    Python 3.13.15 (tags/v3.13.15:4061bc4, Aug 5 2026, 13:05:39) [MSC
    v.1944 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    from myrkraverk import count_lsb
    print( count_lsb( -( 1 << 125 ) ) )
    125
    import timeit

    ## From the above, we can see that my function works, and exists. This
    ## also demonstrates that it totally ignores the sign bit. What follows
    ## is confounding.

    timeit.timeit( "count_lsb( 1 << 125 )" )
    Traceback (most recent call last):
    File "<python-input-7>", line 1, in <module>
    timeit.timeit( "count_lsb( 1 << 125 )" )
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "C:\Opt\Python\3.13\Lib\timeit.py", line 237, in timeit
    return Timer(stmt, setup, timer, globals).timeit(number)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
    File "C:\Opt\Python\3.13\Lib\timeit.py", line 180, in timeit
    timing = self.inner(it, self.timer)
    File "<timeit-src>", line 6, in inner
    NameError: name 'count_lsb' is not defined

    Why doesn't /timeit/ see my C extension function?


    Best wishes, and happy Python benchmarking!

    [1] Here, /digit/ is the 30bit word the internal CPython interpreter
    uses to represent multiprecision integers.
    --
    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 ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann "Myrkraverk" Oskarsson@3:633/10 to All on Sun Sep 20 22:09:56 2026
    On 9/20/2026 9:48 PM, Stefan Ram wrote:
    "Johann \"Myrkraverk\" Oskarsson" <johann@myrkraverk.invalid> wrote or quoted:
    Perhaps I should have made that clearer in the code comments?

    No, I was too focused on just that one line,
    not paying attention to the global context.

    A bit more worrying is that I do not off hand know how to time my cre-
    ation. This is because /timeit/ can't find it.

    Maybe you can pass the globals which should contain the name
    "count_lsb":

    timeit.timeit("count_lsb(1 << 125)", globals=globals())

    . The optional "globals" argument specifies a namespace in
    which to execute the code.

    You could also try the pattern,

    start_time = timeit.default_timer()
    count_lsb(1<<125)
    dt = timeit.default_timer() - start_time

    . However, when "count_lsb(1<<125)` is very fast, the results
    might be less accurate. (You can ask your chatbot about
    "pitfalls of microbenchmarks in Python".)

    Thank you, but the following Python session demonstrates the efforts of
    my work, and that it is indeed significantly faster than the /tradition-
    al/ method.

    n = 1 << 125000
    ( n & -n ).bit_length() - 1
    125000
    def lsb( n ):
    ... return ( n & -n ).bit_length() - 1
    ...
    timeit.timeit( "lsb( n )", globals=globals() )
    3.679828499996802
    timeit.timeit( "lsb( n )", globals=globals() )
    3.6671537999936845
    timeit.timeit( "lsb( n )", globals=globals() )
    3.677232099988032
    timeit.timeit( "count_lsb( n )", globals=globals() )
    0.8524350000079721
    timeit.timeit( "count_lsb( n )", globals=globals() )
    0.8531503000122029
    timeit.timeit( "count_lsb( n )", globals=globals() )
    0.8298240999865811
    timeit.timeit( "count_lsb( n )", globals=globals() )
    0.8146453999797814

    ## So now we have actual numbers to work with. The following snapshot
    ## demonstrates that my effort is approximately 1/5th to 1/4th of the
    ## /original/ in a worst case kind of situation.

    print( 0.8146453999797814 / 3.677232099988032 )
    0.22153766143356377

    ## A proper statistician would of course use averages of multiple runs
    ## of both versions, but I'm sloppy with statistics. After all, I can
    ## demonstrate that my method is faster, and not slower, and don't have
    ## to mess about with the benchmark to give a false impression.

    ## Of course, I do not know how much of a benefit this is, when it comes
    ## to real world cryptography, as I have only a very limited set of num-
    ## bers from Cryptohack so far. The real test will be in making my own
    ## Jacobi Symbol function, and benchmark against the one in SymPy.

    ## I have added sci.math, and sci.crypt, in case they want to comment on
    ## what kind of real world numbers are typically put through a Jacobi
    ## Symbol function, when doing cryptographic research.


    ## Best wishes, and happy cryptography with Python!
    --
    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 ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)