Skip to content

System.Numerics.BigInteger: use LastIndexOfAnyExcept (when relevant) #84855

Open
@speshuric

Description

Description

System.Numerics.BigInteger has a number of methods that look for the first zero (or first non-zero) element. This is usually done by looping through the span/array. It seems that most of them can be rewritten by Span.LastIndexOfAnyExcept() (or similar methods) - this method can be faster than plain loop. Isolated tests show improvement up to 8 times on modern x64 (but any distinct case need clarification).

Click here to expand and show examples

// Pack _bits to remove any wasted space after the twos complement
int len = val.Length - 1;
while (len >= 0 && val[len] == 0) len--;
len++;

// Try to conserve space as much as possible by checking for wasted leading span entries
// sometimes the span has leading zeros from bit manipulation operations & and ^
for (len = value.Length; len > 0 && value[len - 1] == 0; len--);

// Try to conserve space as much as possible by checking for wasted leading span entries
while (dwordCount > 0 && value[dwordCount - 1] == 0) dwordCount--;

// Pack _bits to remove any wasted space after the twos complement
int len = value.Length;
while (len > 0 && value[len - 1] == 0) len--;

while (--iu >= 0)
{
if (_bits[iu] != 0)
return false;
}

while (bits[nonZeroDwordIndex] == 0U)
{
nonZeroDwordIndex++;
}

// Find highest significant byte and ensure high bit is 0 if positive, 1 if negative
int msb = buffer.Length - 2;
while (msb > 0 && buffer[msb] == highDWord)
{
msb--;
}

// Check the rest of the bits (if present)
for (int i = bitsArrayLength - 2; i >= 0; i--)
{
// bits array is always non-null when bitsArrayLength >= 2
if (bits![i] == 0)
continue;
return bitLength;
}

for (int i = 1; (part == 0) && (i < value._bits.Length); i++)
{
part = value._bits[i];
result += (sizeof(uint) * 8);
}

for (int index = 0; index < bits.Length - 1; index++)
{
if (bits[index] != 0)
{
part -= 1;
break;
}
}

for (int index = 0; index < bits.Length - 1; index++)
{
if (bits[index] != 0)
{
part -= 1;
break;
}
}

May be I miss some of them. May be some of them shouldn't use span memory extension methods.

Configuration

Current main branch

Regression?

No

Data

Will be provided

Analysis

Will be provided

Activity

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

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions