DoxigAlpha

llshr

Performs r = a >> shift and returns the amount of limbs affected

if a and r overlaps, then r.ptr <= a.ptr is asserted r must have the capacity to store a >> shift

See tests below for examples of behaviour

Function parameters

Parameters

#
r:[]Limb
a:[]const Limb
shift:usize

Used to indicate either limit of a 2s-complement integer.

Types

#
TwosCompIntLimit
Used to indicate either limit of a 2s-complement integer.
Mutable
A arbitrary-precision big integer, with a fixed set of mutable limbs.
Const
A arbitrary-precision big integer, with a fixed set of immutable limbs.
Managed
An arbitrary-precision big integer along with an allocator which manages the memory.

Returns the number of limbs needed to store `scalar`, which must be a

Functions

#
calcLimbLen
Returns the number of limbs needed to store `scalar`, which must be a
calcSetStringLimbCount
Assumes `string_len` doesn't account for minus signs if the number is negative.
calcNonZeroTwosCompLimbCount
Compute the number of limbs required to store a 2s-complement number of `bit_count` bits.
calcTwosCompLimbCount
Compute the number of limbs required to store a 2s-complement number of `bit_count` bits.
addMulLimbWithCarry
a + b * c + *carry, sets carry to the overflow bits
llcmp
Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively for limbs.

Source

Implementation

#
fn llshr(r: []Limb, a: []const Limb, shift: usize) usize {
    if (slicesOverlap(a, r))
        std.debug.assert(@intFromPtr(r.ptr) <= @intFromPtr(a.ptr));

    if (a.len == 0) return 0;

    if (shift == 0) {
        std.debug.assert(r.len >= a.len);

        if (a.ptr != r.ptr) @memmove(r[0..a.len], a);
        return a.len;
    }
    if (shift >= limb_bits) {
        if (shift / limb_bits >= a.len) {
            r[0] = 0;
            return 1;
        }
        return llshr(r, a[shift / limb_bits ..], shift % limb_bits);
    }

    // shift is guaranteed to be < limb_bits
    const bit_shift: Log2Limb = @truncate(shift);
    const opposite_bit_shift: Log2Limb = @truncate(limb_bits - bit_shift);

    // special case, where there is a risk to set r to 0
    if (a.len == 1) {
        r[0] = a[0] >> bit_shift;
        return 1;
    }
    if (a.len == 0) {
        r[0] = 0;
        return 1;
    }

    // if the most significant limb becomes 0 after the shift
    const shrink = a[a.len - 1] >> bit_shift == 0;
    std.debug.assert(r.len >= a.len - @intFromBool(shrink));

    var i: usize = 0;
    while (i < a.len - 1) : (i += 1) {
        r[i] = (a[i] >> bit_shift) | (a[i + 1] << opposite_bit_shift);
    }

    if (!shrink)
        r[i] = a[i] >> bit_shift;

    return a.len - @intFromBool(shrink);
}