summaryrefslogtreecommitdiffstats log msg author committer range
path: root/pbn_divs.c
blob: 26cc7306ccea57da1164f7f05b8b96003f966e30 (plain)
 ```1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 ``` ``````/* ----------------------------------------------------------------------- * * * 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_divs.c * * "Small division" * * Divide a large number with a small (single-limb) number */ #include "pbnint.h" int pbn_divs(struct pbn **qp, pbn_slimb_t *rp, struct pbn *n, pbn_slimb_t d) { int i; int len; struct pbn *q; pbn_limb_t c; int minus; if (d == 0) { if (rp) *rp = 0; if (qp) *qp = n; else pbn_free(n); return -1; /* Division by zero */ } len = (n->bits+PBN_LIMB_BITS-1)/PBN_LIMB_BITS; q = pbn_new(len); minus = n->minus ^ (d < 0); if (d < 0) d = -d; q->minus = minus; c = 0; for (i = len-1; i >= 0; i--) DIVIDE(c, n->num[i], d, q->num[i], c); pbn_free(n); if (rp) *rp = minus ? -(pbn_slimb_t)c : (pbn_slimb_t)c; if (qp) *qp = pbn_adjust_bits(q); else pbn_free(q); return 0; } ``````