/*
Copyright (C) 2007, 2008 David Harvey (zn_poly)
Copyright (C) 2013 William Hart
This file is part of FLINT.
FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See .
*/
#include
#include
#include "flint.h"
#include "nmod_vec.h"
#include "nmod_poly.h"
/*
Same as _nmod_poly_KS2_pack(), but requires b <= FLINT_BITS.
*/
void
_nmod_poly_KS2_pack1(mp_ptr res, mp_srcptr op, slong n, slong s,
ulong b, ulong k, slong r)
{
/* where to write the next limb */
mp_ptr dest = res;
/* limb currently being filled */
mp_limb_t buf;
/* number of bits used in buf; always in [0, FLINT_BITS) */
ulong buf_b, buf_b_old;
/* write leading zero-padding */
while (k >= FLINT_BITS)
{
*dest++ = 0;
k -= FLINT_BITS;
}
buf = 0;
buf_b = k;
for (; n > 0; n--, op += s)
{
/* put low bits of current input into buffer */
buf += *op << buf_b;
buf_b_old = buf_b;
buf_b += b;
if (buf_b >= FLINT_BITS)
{
/* buffer is full; flush it */
*dest++ = buf;
buf_b -= FLINT_BITS;
/* put remaining bits of current input into buffer */
buf = buf_b_old ? (*op >> (FLINT_BITS - buf_b_old)) : 0;
}
}
/* write last limb if it's non-empty */
if (buf_b)
*dest++ = buf;
/* zero-pad up to requested length */
if (r)
{
slong written = dest - res;
for (; written < r; written++)
*dest++ = 0;
}
}
void
_nmod_poly_KS2_pack(mp_ptr res, mp_srcptr op, slong n, slong s,
ulong b, ulong k, slong r)
{
/* where to write the next limb */
mp_ptr dest = res;
/* limb currently being filled */
mp_limb_t buf;
/* number of bits used in buf; always in [0, FLINT_BITS) */
ulong buf_b, buf_b_old;
if (b <= FLINT_BITS)
{
/* use specialised version if b is small enough */
_nmod_poly_KS2_pack1(res, op, n, s, b, k, r);
return;
}
/* write leading zero-padding */
while (k >= FLINT_BITS)
{
*dest++ = 0;
k -= FLINT_BITS;
}
buf = 0;
buf_b = k;
for (; n > 0; n--, op += s)
{
/* put low bits of current input into buffer */
buf += *op << buf_b;
buf_b_old = buf_b;
buf_b += b;
if (buf_b >= FLINT_BITS)
{
/* buffer is full; flush it */
*dest++ = buf;
buf_b -= FLINT_BITS;
/* put remaining bits of current input into buffer */
buf = buf_b_old ? (*op >> (FLINT_BITS - buf_b_old)) : 0;
/* write as many extra zeroes as necessary */
if (buf_b >= FLINT_BITS)
{
*dest++ = buf;
buf = 0;
buf_b -= FLINT_BITS;
if (buf_b >= FLINT_BITS)
{
*dest++ = 0;
buf_b -= FLINT_BITS;
}
}
}
}
/* write last limb if it's non-empty */
if (buf_b)
*dest++ = buf;
/* zero-pad up to requested length */
if (r)
{
slong written = dest - res;
for (; written < r; written++)
*dest++ = 0;
}
}