Skip to content

Commit

Permalink
Merge pull request #2188 from AllenInstitute/bugfix/2188-fix_popcount
Browse files Browse the repository at this point in the history
Utils: fix function popcount for argument < 0
  • Loading branch information
t-b authored Jul 17, 2024
2 parents 61d08a4 + 538b911 commit 1dd37ab
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
23 changes: 15 additions & 8 deletions Packages/MIES/MIES_Utilities_Numeric.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,26 @@ threadsafe Function ClearBit(var, bit)
End

/// @brief Count the number of ones in `value`
/// Note: if the argument given is not an unsigned int64
/// then it will be implicitly converted to an uint64.
/// This mean e.g. for a double precision argument that
/// the maximum number of bits for positive numbers is 53 from 2^53 - 1
/// and for negative numbers the result is always >= 11.
///
/// @param value will be truncated to an integer value
Function PopCount(value)
variable value
/// @param value will be truncated to an 64 bit unsigned integer value
Function PopCount(uint64 value)

variable count
uint64 leftSideHelper

if(value == 0)
return 0
endif

value = trunc(value)
do
if(value & 1)
count += 1
endif
value = trunc(value / 2^1) // shift one to the right
leftSideHelper = value & 1
count += leftSideHelper
value = value >> 1
while(value > 0)

return count
Expand Down
26 changes: 26 additions & 0 deletions Packages/tests/Basic/UTF_Utils.ipf
Original file line number Diff line number Diff line change
Expand Up @@ -8621,3 +8621,29 @@ static Function FND_Works()
WAVE/Z result = FindNeighbourDuplicates({1, NaN, NaN, Inf, -Inf, Inf, Inf, 2})
CHECK_EQUAL_WAVES(result, {2, 6}, mode = WAVE_DATA)
End

static Function PopCount_Works()

uint64 ui

CHECK_EQUAL_VAR(PopCount(0), 0)
CHECK_EQUAL_VAR(PopCount(1), 1)
CHECK_EQUAL_VAR(PopCount(2), 1)
CHECK_EQUAL_VAR(PopCount(3), 2)
CHECK_EQUAL_VAR(PopCount(7), 3)
CHECK_EQUAL_VAR(PopCount(15), 4)
// negative numbers are represented as two's complement
CHECK_EQUAL_VAR(PopCount(-1), 64)
CHECK_EQUAL_VAR(PopCount(-2), 63)
CHECK_EQUAL_VAR(PopCount(-3), 63)
CHECK_EQUAL_VAR(PopCount(-4), 62)
// non-finite numbers get implicitly converted to 0x8000000000000000
CHECK_EQUAL_VAR(PopCount(NaN), 1)
CHECK_EQUAL_VAR(PopCount(Inf), 1)
CHECK_EQUAL_VAR(PopCount(-Inf), 1)
// tests when no implicit conversion takes place
ui = 0xAAAAAAAAAAAAAAAA
CHECK_EQUAL_VAR(PopCount(ui), 32)
ui = 0x5555555555555555
CHECK_EQUAL_VAR(PopCount(ui), 32)
End

0 comments on commit 1dd37ab

Please sign in to comment.