Skip to content

Fix bug in log2_fx with binary circuits - #1809

Open
rdeviti wants to merge 1 commit into
data61:masterfrom
rdeviti:popcnt-bits-vector-length
Open

rdeviti wants to merge 1 commit into
data61:masterfrom
rdeviti:popcnt-bits-vector-length

Conversation

@rdeviti

@rdeviti rdeviti commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

In binary circuits, the function mpc_math.log2_fx can return wrong values at small precisions. I found this while testing #1796, which fixed popcnt returning a count one bit too short for some lengths, so I checked log2_fx, which uses popcnt in binary circuits. For instance, with Scripts/compile-run.py -E replicated, the following snippet prints -5.5 for log2(8):

from Compiler import mpc_math
sfix.set_precision(2, 7)
for x in (1, 2, 4, 8):
    print_ln("log2(%s) = %s", x, mpc_math.log2_fx(sfix(x)).reveal())

It prints -0.5, 0.5, 1.5 and -5.5. The first three are 0.5 below the exact values, but -5.5 is far off. With this PR, log2(8) gives 2.5, which is consistent with the other outputs as log2_fx is only approximate with 2 fractional bits.

Cause

log2_fx calls floatingpoint.Int2FL, which computes the exponent as a.popcnt_bits(b) - lam. In binary circuits, a is an sbitintvec of k bits, 7 in the snippet. But sbitintvec.popcnt_bits returns the count as a 3-bit number, just wide enough for counts up to 6, so the exponent overflows.

Fix

I patched sbitintvec.popcnt_bits so it behaves like sbitint.popcnt_bits, returning the count with as many bits as the integer it is called on.

Testing

  • I added a check to test_gc.mpc that the count has as many bits as the integer.
  • I tested log2_fx with 21 precisions, with k from 5 to 31, on up to six powers of two, from 2**-f to the largest that fits: without the fix, 3 precisions give a value off by 1 or more, all with k of 12 or less: (k, f) = (7, 2), (11, 2) and (12, 2). With the fix, none does, and the values that were right before are unchanged.
  • With this PR, including the new check, Scripts/compile-run.py -E ring test_gc and -E replicated test_gc print the same output as master's test_gc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant