-void mpx_lslc(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl, size_t n)
-{
- size_t nw;
- unsigned nb;
-
- /* --- Trivial special case --- */
-
- if (n == 0)
- MPX_COPY(dv, dvl, av, avl);
-
- /* --- Single bit shifting --- */
-
- else if (n == 1) {
- mpw w = 1;
- while (av < avl) {
- mpw t;
- if (dv >= dvl)
- goto done;
- t = *av++;
- *dv++ = MPW((t << 1) | w);
- w = t >> (MPW_BITS - 1);
- }
- if (dv >= dvl)
- goto done;
- *dv++ = MPW(w);
- MPX_ZERO(dv, dvl);
- goto done;
- }
-
- /* --- Break out word and bit shifts for more sophisticated work --- */
-
- nw = n / MPW_BITS;
- nb = n % MPW_BITS;
-
- /* --- Handle a shift by a multiple of the word size --- */
-
- if (nb == 0) {
- if (nw >= dvl - dv)
- MPX_ONE(dv, dvl);
- else {
- MPX_COPY(dv + nw, dvl, av, avl);
- MPX_ONE(dv, dv + nw);
- }
- }
-
- /* --- And finally the difficult case --- *
- *
- * This is a little convoluted, because I have to start from the end and
- * work backwards to avoid overwriting the source, if they're both the same
- * block of memory.
- */
-
- else {
- mpw w;
- size_t nr = MPW_BITS - nb;
- size_t dvn = dvl - dv;
- size_t avn = avl - av;
-
- if (dvn <= nw) {
- MPX_ONE(dv, dvl);
- goto done;
- }
-
- if (dvn > avn + nw) {
- size_t off = avn + nw + 1;
- MPX_ZERO(dv + off, dvl);
- dvl = dv + off;
- w = 0;
- } else {
- avl = av + dvn - nw;
- w = *--avl << nb;
- }
-
- while (avl > av) {
- mpw t = *--avl;
- *--dvl = MPW((t >> nr) | w);
- w = t << nb;
- }
-
- *--dvl = MPW((MPW_MAX >> nr) | w);
- MPX_ONE(dv, dvl);
- }
-
-done:;
-}