From 75e09b3c4b9d50b23e02b4531748e1121c6db420 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 20 Mar 2012 16:20:43 -0700 Subject: Add pbn_mulus_add() Add pbn_mulus_add(); equivalent to pbn_muls() except: a) it takes an unsigned multiplier, and b) it takes a second single-limb unsigned addend. It thus computes * + ; this is highly useful in base conversion. --- Makefile | 3 ++- pbn.h | 3 +++ pbn_mulus_add.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 pbn_mulus_add.c diff --git a/Makefile b/Makefile index 7b3cbfb..8c51013 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,8 @@ LDFLAGS = AR = ar RANLIB = ranlib -LIBOBJ = pbn_add.o pbn_cmp.o pbn_dump.o pbn_init.o pbn_mul.o pbn_muls.o \ +LIBOBJ = pbn_add.o pbn_cmp.o pbn_dump.o pbn_init.o \ + pbn_mul.o pbn_muls.o pbn_mulus_add.o \ pbn_shift.o pbn_and.o pbn_or.o pbn_xor.o pbn_bit.o pbn_ctz.o \ pbn_abs.o pbn_div.o pbn_divs.o diff --git a/pbn.h b/pbn.h index afc5249..27cf9b4 100644 --- a/pbn.h +++ b/pbn.h @@ -67,6 +67,7 @@ int pbn_cmp(const struct pbn *, const struct pbn *); int pbn_abscmp(const struct pbn *, const struct pbn *); struct pbn *pbn_mul(struct pbn *, struct pbn *); struct pbn *pbn_muls(struct pbn *, pbn_slimb_t); +struct pbn *pbn_mulus_add(struct pbn *, pbn_limb_t, pbn_limb_t); int pbn_div(struct pbn **, struct pbn **, struct pbn *, struct pbn *); int pbn_divs(struct pbn **, pbn_slimb_t *, struct pbn *, pbn_slimb_t); struct pbn *pbn_abs(struct pbn *); @@ -76,6 +77,8 @@ struct pbn *pbn_shl(struct pbn *, int); struct pbn *pbn_and(struct pbn *, struct pbn *); struct pbn *pbn_or(struct pbn *, struct pbn *); struct pbn *pbn_xor(struct pbn *, struct pbn *); +/* pbn_ctz() does NOT consume a reference! */ +int pbn_ctz(const struct pbn *); struct pbn *pbn_set_bit(struct pbn *, int); struct pbn *pbn_clr_bit(struct pbn *, int); diff --git a/pbn_mulus_add.c b/pbn_mulus_add.c new file mode 100644 index 0000000..23ec240 --- /dev/null +++ b/pbn_mulus_add.c @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, Inc., + * 59 Temple Place Ste 330, Boston MA 02111-1307, USA; version 2.1, + * incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * pbn_mulus_add.c + * + * Multiply a PBN with a single limb unsigned number, and add a single + * limb unsigned number. + */ + +#include "pbnint.h" + +struct pbn *pbn_mulus_add(struct pbn *s1, pbn_limb_t s2, pbn_limb_t c) +{ + size_t i, len; + struct pbn *d; + pbn_limb_t *s1p, *dp; + pbn_2limb_t t; + + if (unlikely(s1->bits == 0)) { + pbn_free(s1); + return pbn_uint(c); + } + + len = (s1->bits+PBN_LIMB_BITS-1) >> PBN_LIMB_SHIFT; + + d = pbn_new(len+1); + d->minus = s1->minus; + + s1p = s1->num; + dp = d->num; + for (i = 0; i < len; i++) { + t = (pbn_2limb_t)*s1p++ * s2 + c; + *dp++ = (pbn_limb_t)t; + c = t >> PBN_LIMB_BITS; + } + *dp = c; + + pbn_free(s1); + + return pbn_adjust_bits(d); +} -- cgit v1.2.3