Modifying pidigits of Computer Language Benchmark Game for Lua 5.4.8

Modifying pidigits of Computer Language Benchmark Game for Lua 5.4.8

Problem #

pidigits need lgmp large number library

lgmp is not available for Lua 5.4.x

lgmp is only available in luarocks for up to Lua 5.3.6

pidigits.lua from CLBG site just use some kind of ‘bn’ library, but the library is not given.

in original code, ‘bn’ library is loaded with the following code:

local Lbn=require"bn"

which gives error:

lua: pidigits.lua:7: module 'bn' not found:
        no field package.preload['bn']
        no file '/usr/local/share/lua/5.4/bn.lua'
        no file '/usr/local/share/lua/5.4/bn/init.lua'
        no file '/usr/local/lib/lua/5.4/bn.lua'
        no file '/usr/local/lib/lua/5.4/bn/init.lua'
        no file './bn.lua'
        no file './bn/init.lua'
        no file '/usr/local/lib/lua/5.4/bn.so'
        no file '/usr/local/lib/lua/5.4/loadall.so'
        no file './bn.so'
stack traceback:
        [C]: in function 'require'
        pidigits.lua:7: in main chunk
        [C]: in ?

Reading from the CLBG site does not offer clue how to install this ‘bn’ library.

Install lua-openssh #

After searching for ‘big number library for Lua’, or ‘bn.lua’, I found a solution.

Alternative is to use big number libraray (bn) from lua-openssh

How to install with luarocks:

luarocks install openssl

Other installation method: https://zhaozg.github.io/lua-openssl/topics/README.md.html#quick-start

Modify pidigits.Lua #

Modification: change the line to:

local Lbn=require('openssl').bn

According to https://zhaozg.github.io/lua-openssl/modules/bn.html

Final Code #

-- The Computer Language Benchmarks Game
-- https://salsa.debian.org/benchmarksgame-team/benchmarksgame/

-- Translated from Mr Ledrug's C program by Jeremy Zerfas.
-- Transliterated from GMP to bn by Isaac Gouy

local Lbn=require('openssl').bn
local add, sub, mul, div = Lbn.add, Lbn.sub, Lbn.mul, Lbn.div
local set, get = Lbn.number, Lbn.tonumber

local tmp1, tmp2, acc, den, num

local function extractDigit(nth)
    tmp1 = mul(num, nth)
    tmp2 = add(tmp1, acc)
    tmp1 = div(tmp2, den)
    return tmp1
end

local function eliminateDigit(d)
    acc = sub(acc, mul(den, d))
    acc = mul(acc, 10)
    num = mul(num, 10)
end

local function nextTerm(k)
    k2 = k * 2 + 1
    acc = add(acc, mul(num, 2))
    acc = mul(acc, k2)
    den = mul(den, k2)
    num = mul(num, k)
end

local function main(n)
    local write = io.write
    tmp1 = set(0)
    tmp2 = set(0)
    acc = set(0)
    den = set(1)
    num = set(1)
    i = 0
    k = 0
    while i < n do
        k = k + 1
        nextTerm(k)
        if num > acc then goto continue end

        d = extractDigit(3)
        if d ~= extractDigit(4) then goto continue end

        write(get(d))
        i = i + 1; if i % 10 == 0 then write("\t:", i, "\n") end
        eliminateDigit(d)
        ::continue::
    end
    if i % 10 ~= 0 then write(string.rep(" ", 10 - n % 10), "\t:", n, "\n") end
end

main(tonumber(arg and arg[1]) or 27)
(base) root@z170:/home/waskita/plee/bench-clbg/benchmarksgame-sourcecode-2025-03-07/pidigits# more p.lua
-- The Computer Language Benchmarks Game
-- https://salsa.debian.org/benchmarksgame-team/benchmarksgame/

-- Translated from Mr Ledrug's C program by Jeremy Zerfas.
-- Transliterated from GMP to bn by Isaac Gouy

local Lbn=require('openssl').bn
local add, sub, mul, div = Lbn.add, Lbn.sub, Lbn.mul, Lbn.div
local set, get = Lbn.number, Lbn.tonumber

local tmp1, tmp2, acc, den, num

local function extractDigit(nth)
    tmp1 = mul(num, nth)
    tmp2 = add(tmp1, acc)
    tmp1 = div(tmp2, den)
    return tmp1
end

local function eliminateDigit(d)
    acc = sub(acc, mul(den, d))
    acc = mul(acc, 10)
    num = mul(num, 10)
end

local function nextTerm(k)
    k2 = k * 2 + 1
    acc = add(acc, mul(num, 2))
    acc = mul(acc, k2)
    den = mul(den, k2)
    num = mul(num, k)
end

local function main(n)
    local write = io.write
    tmp1 = set(0)
    tmp2 = set(0)
    acc = set(0)
    den = set(1)
    num = set(1)
    i = 0
    k = 0
    while i < n do
        k = k + 1
        nextTerm(k)
        if num > acc then goto continue end

        d = extractDigit(3)
        if d ~= extractDigit(4) then goto continue end

        write(get(d))
        i = i + 1; if i % 10 == 0 then write("\t:", i, "\n") end
        eliminateDigit(d)
        ::continue::
    end
    if i % 10 ~= 0 then write(string.rep(" ", 10 - n % 10), "\t:", n, "\n") end
end

main(tonumber(arg and arg[1]) or 27)

And it finally works.

References #