X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/bc97f84ce8a8cb1d0476ec4128ca59c40d98e5d5..ae747c9bab929bc794ddad9f59c381657d347d1f:/gfx-sqr.c diff --git a/gfx-sqr.c b/gfx-sqr.c new file mode 100644 index 0000000..b253a32 --- /dev/null +++ b/gfx-sqr.c @@ -0,0 +1,222 @@ +/* -*-c-*- + * + * $Id: gfx-sqr.c,v 1.1 2000/10/08 15:49:37 mdw Exp $ + * + * Sqaring binary polynomials + * + * (c) 2000 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of Catacomb. + * + * Catacomb is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Catacomb is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with Catacomb; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: gfx-sqr.c,v $ + * Revision 1.1 2000/10/08 15:49:37 mdw + * First glimmerings of binary polynomial arithmetic. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "mpx.h" +/* #include "gfx.h" */ +#include "gfx-sqr-tab.h" + +/*----- Static variables --------------------------------------------------*/ + +static uint16 tab[256] = GFX_SQRTAB; + +/*----- Main code ---------------------------------------------------------*/ + +/* --- @gfx_sqr@ --- * + * + * Arguments: @mpw *dv, *dvl@ = destination vector base and limit + * @const mpw *av, *avl@ = argument vector base and limit + * + * Returns: --- + * + * Use: Performs squaring of binary polynomials. + */ + +void gfx_sqr(mpw *dv, mpw *dvl, const mpw *av, const mpw *avl) +{ + mpd a = 0, aa = 0; + unsigned b = 0, bb = 0; + + /* --- Simple stuff --- */ + + if (dv >= dvl) + return; + MPX_SHRINK(av, avl); + + /* --- The main algorithm --- * + * + * Our method depends on the fact that, in a field of characteristic 2, we + * have that %$(a + b)^2 = a^2 + b^2$%. Thus, to square a polynomial, it's + * sufficient just to put a zero bit between each of the bits of the + * original argument. We use a precomputed table for this, and work on + * entire octets at a time. Life is more complicated because we've got to + * be careful of bizarre architectures which don't have words with a + * multiple of 8 bits in them. + */ + + for (;;) { + + /* --- Input buffering --- */ + + if (b < 8) { + if (av >= avl) + break; + a |= *av++ << b; + b += MPW_BITS; + } + + /* --- Do the work in the middle --- */ + + aa |= (mpd)(tab[U8(a)]) << bb; + bb += 16; + a >>= 8; + b -= 8; + + /* --- Output buffering --- */ + + if (bb > MPW_BITS) { + *dv++ = MPW(aa); + if (dv >= dvl) + return; + aa >>= MPW_BITS; + bb -= MPW_BITS; + } + } + + /* --- Flush the input buffer --- */ + + if (b) for (;;) { + aa |= (mpd)(tab[U8(a)]) << bb; + bb += 16; + if (bb > MPW_BITS) { + *dv++ = MPW(aa); + if (dv >= dvl) + return; + aa >>= MPW_BITS; + bb -= MPW_BITS; + } + a >>= 8; + if (b <= 8) + break; + else + b -= 8; + } + + /* --- Flush the output buffer --- */ + + if (bb) for (;;) { + *dv++ = MPW(aa); + if (dv >= dvl) + return; + aa >>= MPW_BITS; + if (bb <= MPW_BITS) + break; + else + bb -= MPW_BITS; + } + + /* --- Zero the rest of everything --- */ + + MPX_ZERO(dv, dvl); +} + +/*----- Test rig ----------------------------------------------------------*/ + +#ifdef TEST_RIG + +#include +#include +#include +#include + +#define ALLOC(v, vl, sz) do { \ + size_t _sz = (sz); \ + mpw *_vv = xmalloc(MPWS(_sz)); \ + mpw *_vvl = _vv + _sz; \ + (v) = _vv; \ + (vl) = _vvl; \ +} while (0) + +#define LOAD(v, vl, d) do { \ + const dstr *_d = (d); \ + mpw *_v, *_vl; \ + ALLOC(_v, _vl, MPW_RQ(_d->len)); \ + mpx_loadb(_v, _vl, _d->buf, _d->len); \ + (v) = _v; \ + (vl) = _vl; \ +} while (0) + +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +static void dumpmp(const char *msg, const mpw *v, const mpw *vl) +{ + fputs(msg, stderr); + MPX_SHRINK(v, vl); + while (v < vl) + fprintf(stderr, " %08lx", (unsigned long)*--vl); + fputc('\n', stderr); +} + +static int vsqr(dstr *v) +{ + mpw *a, *al; + mpw *b, *bl; + mpw *d, *dl; + int ok = 1; + + LOAD(a, al, &v[0]); + LOAD(b, bl, &v[1]); + ALLOC(d, dl, 2 * (al - a)); + + gfx_sqr(d, dl, a, al); + if (!mpx_ueq(d, dl, b, bl)) { + fprintf(stderr, "\n*** vsqr failed\n"); + dumpmp(" a", a, al); + dumpmp("expected", b, bl); + dumpmp(" result", d, dl); + ok = 0; + } + + free(a); free(b); free(d); + return (ok); +} + +static test_chunk defs[] = { + { "sqr", vsqr, { &type_hex, &type_hex, 0 } }, + { 0, 0, { 0 } } +}; + +int main(int argc, char *argv[]) +{ + test_run(argc, argv, defs, SRCDIR"/tests/gfx"); + return (0); +} + +#endif + +/*----- That's all, folks -------------------------------------------------*/