/* < 0 means right shift, > 0 means left shift */ void mpi_shift(const mpi *p, int bits, mpi *q) { if (bits < 0) mpi_rshift(p, -bits, q); else if (bits > 0) mpi_lshift(p, +bits, q); }
void mpi_mul_u64(const mpi *a, uint64_t b, mpi *p) { if (mpi_is_zero(a) || b == 0) { mpi_zero(p); return; } else if (b == 1) { if (a != p) mpi_set_mpi(p, a); return; } else if ((b & (b-1)) == 0) { /* B is a power of 2 */ mpi_lshift(a, __builtin_ctzll(b), p); return; } else if (b == (mp_digit)b) { /* B fits in an mp_digit */ if (a == p) { mp_digit cy = mp_dmuli(p->digits, p->size, (mp_digit)b); if (cy) { MPI_MIN_ALLOC(p, p->size + 1); p->digits[p->size++] = cy; } } else { MPI_MIN_ALLOC(p, a->size); mp_digit cy = mp_dmul(a->digits, a->size, (mp_digit)b, p->digits); if (cy) { MPI_MIN_ALLOC(p, a->size + 1); p->digits[a->size] = cy; p->size = a->size + 1; } else { p->size = a->size; } } } else { unsigned bits = CHAR_BIT * sizeof(uint64_t) - __builtin_clzll(b); mp_size size = (bits + MP_DIGIT_BITS - 1) / MP_DIGIT_BITS; mp_digit *bp = MP_TMP_ALLOC(size); #if MP_DIGIT_BITS >= 64 bp[0] = b; #else for (mp_size j=0; j<size; j++) { bp[j] = (mp_digit)b; b >>= MP_DIGIT_BITS; } #endif if (a == p) { mp_digit *tmp = MP_TMP_ALLOC(p->size + size); mp_mul(p->digits, p->size, bp, size, tmp); MPI_MIN_ALLOC(p, p->size + size); mp_copy(tmp, p->size + size, p->digits); p->size = mp_rsize(p->digits, p->size + size); MP_TMP_FREE(tmp); } else { MPI_MIN_ALLOC(p, a->size + size); mp_mul(a->digits, a->size, bp, size, p->digits); p->size = mp_rsize(p->digits, a->size + size); } MP_TMP_FREE(bp); } }
static void do_lshift (void) { if (stackidx < 1) { fputs ("stack underflow\n", stderr); return; } mpi_lshift (stack[stackidx - 1], stack[stackidx - 1], 1); }