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
73 changes: 16 additions & 57 deletions std/bitmanip.d
Original file line number Diff line number Diff line change
Expand Up @@ -3773,57 +3773,6 @@ void append(T, Endian endianness = Endian.bigEndian, R)(R range, T value)
}
}

/**
Counts the number of trailing zeros in the binary representation of $(D value).
For signed integers, the sign bit is included in the count.
*/
private uint countTrailingZeros(T)(T value) @nogc pure nothrow
if (isIntegral!T)
{
import core.bitop : bsf;
// bsf doesn't give the correct result for 0.
if (!value)
return 8 * T.sizeof;
else
return bsf(value);
}

///
@safe unittest
{
assert(countTrailingZeros(1) == 0);
assert(countTrailingZeros(0) == 32);
assert(countTrailingZeros(int.min) == 31);
assert(countTrailingZeros(256) == 8);
}

@safe unittest
{
import std.meta;
foreach (T; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
{
assert(countTrailingZeros(cast(T)0) == 8 * T.sizeof);
assert(countTrailingZeros(cast(T)1) == 0);
assert(countTrailingZeros(cast(T)2) == 1);
assert(countTrailingZeros(cast(T)3) == 0);
assert(countTrailingZeros(cast(T)4) == 2);
assert(countTrailingZeros(cast(T)5) == 0);
assert(countTrailingZeros(cast(T)64) == 6);
static if (isSigned!T)
{
assert(countTrailingZeros(cast(T)-1) == 0);
assert(countTrailingZeros(T.min) == 8 * T.sizeof - 1);
}
else
{
assert(countTrailingZeros(T.max) == 0);
}
}
assert(countTrailingZeros(1_000_000) == 6);
foreach (i; 0..63)
assert(countTrailingZeros(1UL << i) == i);
}

/**
Counts the number of set bits in the binary representation of $(D value).
For signed integers, the sign bit is included in the count.
Expand Down Expand Up @@ -3914,9 +3863,14 @@ private struct BitsSet(T)
this(T value, size_t startIndex = 0)
{
_value = value;
immutable n = countTrailingZeros(value);
_index = startIndex + n;
_value >>>= n;
// Further calculation is only valid and needed when the range is non-empty.
if (!_value)
return;

import core.bitop : bsf;
immutable trailingZerosCount = bsf(value);
_value >>>= trailingZerosCount;
_index = startIndex + trailingZerosCount;
}

@property size_t front()
Expand All @@ -3934,9 +3888,14 @@ private struct BitsSet(T)
assert(_value, "Cannot call popFront on empty range.");

_value >>>= 1;
immutable n = countTrailingZeros(_value);
_value >>>= n;
_index += n + 1;
// Further calculation is only valid and needed when the range is non-empty.
if (!_value)
return;

import core.bitop : bsf;
immutable trailingZerosCount = bsf(_value);
_value >>>= trailingZerosCount;
_index += trailingZerosCount + 1;
}

@property auto save()
Expand Down