Function shiftLeftSat [src]

r = a <<| shift with 2s-complement saturating semantics. r and a may alias. Asserts there is enough memory to fit the result. The upper bound Limb count is r is calcTwosCompLimbCount(bit_count).

Prototype

pub fn shiftLeftSat(r: *Mutable, a: Const, shift: usize, signedness: Signedness, bit_count: usize) void

Parameters

r: *Mutablea: Constshift: usizesignedness: Signednessbit_count: usize

Source

pub fn shiftLeftSat(r: *Mutable, a: Const, shift: usize, signedness: Signedness, bit_count: usize) void { // Special case: When the argument is negative, but the result is supposed to be unsigned, // return 0 in all cases. if (!a.positive and signedness == .unsigned) { r.set(0); return; } // Check whether the shift is going to overflow. This is the case // when (in 2s complement) any bit above `bit_count - shift` is set in the unshifted value. // Note, the sign bit is not counted here. // Handle shifts larger than the target type. This also deals with // 0-bit integers. if (bit_count <= shift) { // In this case, there is only no overflow if `a` is zero. if (a.eqlZero()) { r.set(0); } else { r.setTwosCompIntLimit(if (a.positive) .max else .min, signedness, bit_count); } return; } const checkbit = bit_count - shift - @intFromBool(signedness == .signed); // If `checkbit` and more significant bits are zero, no overflow will take place. if (checkbit >= a.limbs.len * limb_bits) { // `checkbit` is outside the range of a, so definitely no overflow will take place. We // can defer to a normal shift. // Note that if `a` is normalized (which we assume), this checks for set bits in the upper limbs. // Note, in this case r should already have enough limbs required to perform the normal shift. // In this case the shift of the most significant limb may still overflow. r.shiftLeft(a, shift); return; } else if (checkbit < (a.limbs.len - 1) * limb_bits) { // `checkbit` is not in the most significant limb. If `a` is normalized the most significant // limb will not be zero, so in this case we need to saturate. Note that `a.limbs.len` must be // at least one according to normalization rules. r.setTwosCompIntLimit(if (a.positive) .max else .min, signedness, bit_count); return; } // Generate a mask with the bits to check in the most significant limb. We'll need to check // all bits with equal or more significance than checkbit. // const msb = @truncate(Log2Limb, checkbit); // const checkmask = (@as(Limb, 1) << msb) -% 1; if (a.limbs[a.limbs.len - 1] >> @as(Log2Limb, @truncate(checkbit)) != 0) { // Need to saturate. r.setTwosCompIntLimit(if (a.positive) .max else .min, signedness, bit_count); return; } // This shift should not be able to overflow, so invoke llshl and normalize manually // to avoid the extra required limb. llshl(r.limbs, a.limbs, shift); r.normalize(a.limbs.len + (shift / limb_bits)); r.positive = a.positive; }