#include #include // ----------------------------------------------------------------------------- void identity(int n, const uint64_t *src, int* pm, uint64_t *tgt) { memcpy(tgt, src, n<<3); *pm = n; } void cons(uint64_t x, int n, const uint64_t *src, int* pm, uint64_t *tgt) { memcpy(tgt+1, src, n<<3); tgt[0] = x; *pm = n+1; } void snoc(uint64_t x, int n, const uint64_t *src, int* pm, uint64_t *tgt) { memcpy(tgt, src, n<<3); tgt[n] = x; *pm = n+1; } void tail(int n, const uint64_t *src, int* pm, uint64_t *tgt) { if (n>1) { memcpy(tgt, src+1, (n-1)<<3); *pm = n-1; } else { tgt[0] = 0; *pm = 1; } } // ----------------------------------------------------------------------------- #define IDX_RIGHT(i,shift) ( ( (i) + (shift) ) % n ) #define IDX_LEFT( i,shift) ( ( (i) + n - (shift) ) % n ) void rotate_left_words(int k0, int n, const uint64_t *src, int* pm, uint64_t *tgt) { int k = k0 % n; for(int i=0;i> r); x = src[i]; } *pm = n; } // we assume that 0 <= k < 64 void rotate_right_bits(int k, int n, const uint64_t *src, int* pm, uint64_t *tgt) { if (k==0) { identity(n,src,pm,tgt); return; } int r = 64 - k; uint64_t x = src[n-1]; for(int i=0;i> k) | (src[i+1] << r); } tgt[n-1] = (src[n-1] >> k) | (src[0] << r); *pm = n; } void rotate_left(int k0, int n, const uint64_t *src, int* pm, uint64_t *tgt) { if (k0==0) { identity(n,src,pm,tgt); return; } int k = k0 & 63; int s = (k0 >> 6) % n; int r = 64 - k; uint64_t x = src[ IDX_LEFT(n-1,s) ]; if (k==0) { rotate_left_words(s,n,src,pm,tgt); return; } if (s==0) { rotate_left_bits (k,n,src,pm,tgt); return; } for(int i=0;i> r); x = src[o]; } *pm = n; } void rotate_right(int k0, int n, const uint64_t *src, int* pm, uint64_t *tgt) { if (k0==0) { identity(n,src,pm,tgt); return; } int k = k0 & 63; int s = (k0 >> 6) % n; int r = 64 - k; uint64_t x = src[ IDX_RIGHT(n-1,s) ]; if (k==0) { rotate_right_words(s,n,src,pm,tgt); return; } if (s==0) { rotate_right_bits (k,n,src,pm,tgt); return; } for(int i=0;i> k) | ( src[ IDX_RIGHT(i+1,s)] << r); } *pm = n; } // ----------------------------------------------------------------------------- void shift_left_words(int k, int n, const uint64_t *src, int* pm, uint64_t *tgt) { for(int i=0;i= n) { tgt[0]=0; *pm=1; return; } for(int i=0;i> r); x = src[i]; } // always increase the size tgt[n] = (x >> r); *pm = n+1; } // we assume that 0 <= k < 64 // non-strict version: we adopt the convention here that blobs are // extended with zeros to infinity, and only increase the size if necessary void shift_left_bits_nonstrict(int k, int n, const uint64_t *src, int* pm, uint64_t *tgt) { if (k==0) { identity(n,src,pm,tgt); return; } int r = 64 - k; uint64_t x = 0; for(int i=0;i> r); x = src[i]; } // we adopt the convention here that blobs are extended with zeros to infinity // and only increase the size if necessary uint64_t y = (x >> r); if (y==0) { *pm = n; } else { tgt[n] = y; *pm = n+1; } // tgt[n] = (x >> r); // *pm = n+1; } // we assume that 0 <= k < 64 void shift_right_bits(int k, int n, const uint64_t *src, int* pm, uint64_t *tgt) { if (k==0) { identity(n,src,pm,tgt); return; } int r = 64 - k; for(int i=0;i> k) | (src[i+1] << r); } tgt[n-1] = src[n-1] >> k; *pm = n; } // strict version: we _always_ increase the size void shift_left_strict(int k0, int n, const uint64_t *src, int* pm, uint64_t *tgt) { if (k0==0) { identity(n,src,pm,tgt); return; } int k = k0 & 63; int s = (k0 >> 6); int r = 64 - k; if (k==0) { shift_left_words(s,n,src,pm,tgt); return; } if (s==0) { shift_left_bits_strict(k,n,src,pm,tgt); return; } for(int i=0;i> r); x = src[i]; } // we always always increase tgt[n+s] = (x >> r); *pm = n+s+1; } // non-strict version: // we adopt the convention here that blobs are extended with // zeros to infinity and only increase the size if necessary void shift_left_nonstrict(int k0, int n, const uint64_t *src, int* pm, uint64_t *tgt) { if (k0==0) { identity(n,src,pm,tgt); return; } int k = k0 & 63; int s = (k0 >> 6); int r = 64 - k; if (k==0) { shift_left_words (s,n,src,pm,tgt); return; } if (s==0) { shift_left_bits_nonstrict (k,n,src,pm,tgt); return; } for(int i=0;i> r); x = src[i]; } // we adopt the convention here that blobs are extended with zeros to infinity // and only increase the size if necessary uint64_t y = (x >> r); if (y==0) { *pm = n+s; } else { tgt[n+s] = y; *pm = n+s+1; } } void shift_right(int k0, int n, const uint64_t *src, int* pm, uint64_t *tgt) { if (k0==0) { identity(n,src,pm,tgt); return; } int k = k0 & 63; int s = (k0 >> 6); int r = 64 - k; if (k==0) { shift_right_words(s,n,src,pm,tgt); return; } if (s==0) { shift_right_bits (k,n,src,pm,tgt); return; } for(int i=0;i> k) | (src[i+s+1] << r); } tgt[n-s-1] = src[n-1] >> k; *pm = n-s; } // -----------------------------------------------------------------------------