Skip to content
Merged
Changes from all commits
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
51 changes: 50 additions & 1 deletion test/src/lib/LibCtPop.ctpop.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,18 @@
pragma solidity =0.8.25;

import {Test} from "forge-std-1.16.1/src/Test.sol";
import {LibCtPop} from "src/lib/LibCtPop.sol";
import {
LibCtPop,
CTPOP_M1,
CTPOP_M2,
CTPOP_M4,
CTPOP_M8,
CTPOP_M16,
CTPOP_M32,
CTPOP_M64,
CTPOP_M128,
CTPOP_H01
} from "../../../src/lib/LibCtPop.sol";

/// @title LibCtPopTest
/// CTPOP (count population) is a function that counts the number of bits set in
Expand Down Expand Up @@ -72,4 +83,42 @@ contract LibCtPopTest is Test {
uint256 ctSlow = LibCtPop.ctpopSlow(x);
assertEq(ct, ctSlow);
}

/// A lone bit in the highest position is counted, deterministically
/// pinning the top of the range rather than relying on fuzz coverage.
function testCtPopLoneHighBit() external pure {
uint256 x = 1 << 255;
assertEq(1, LibCtPop.ctpop(x));
assertEq(1, LibCtPop.ctpopSlow(x));
}

/// Build the alternating mask with `width` bits set then `width` bits
/// clear, starting from the low bit, across the whole word.
function altMask(uint256 width) internal pure returns (uint256 mask) {
unchecked {
uint256 chunk = (1 << width) - 1;
for (uint256 i = 0; i < 256; i += 2 * width) {
mask |= chunk << i;
}
}
}

/// Every mask constant is pinned against an independent re-derivation so
/// a corrupted constant cannot hide behind ctpop and ctpopSlow sharing it.
function testMaskConstantsRederived() external pure {
assertEq(altMask(1), CTPOP_M1);
assertEq(altMask(2), CTPOP_M2);
assertEq(altMask(4), CTPOP_M4);
assertEq(altMask(8), CTPOP_M8);
assertEq(altMask(16), CTPOP_M16);
assertEq(altMask(32), CTPOP_M32);
assertEq(altMask(64), CTPOP_M64);
assertEq(altMask(128), CTPOP_M128);

uint256 h01 = 0;
for (uint256 i = 0; i < 256; i += 8) {
h01 |= uint256(1) << i;
}
assertEq(h01, CTPOP_H01);
}
}
Loading