1 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
   2 /*        All Rights Reserved   */
   3 
   4 
   5 /*
   6  * Copyright (c) 1980 Regents of the University of California.
   7  * All rights reserved.  The Berkeley software License Agreement
   8  * specifies the terms and conditions for redistribution.
   9  */
  10 /*      Portions Copyright(c) 1988, Sun Microsystems Inc.       */
  11 /*      All Rights Reserved                                     */
  12 
  13 /*
  14  * Copyright (c) 1997, by Sun Microsystems, Inc.
  15  * All rights reserved.
  16  */
  17 
  18 #ident  "%Z%%M% %I%     %E% SMI"        /* SVr4.0 1.1   */
  19 
  20 /* LINTLIBRARY */
  21 
  22 #include <mp.h>
  23 #include <stdio.h>
  24 #include <stdlib.h>
  25 #include <sys/types.h>
  26 #include "libmp.h"
  27 
  28 static void m_div(MINT *, MINT *, MINT *, MINT *);
  29 
  30 void
  31 mp_mdiv(MINT *a, MINT *b, MINT *q, MINT *r)
  32 {
  33         MINT x, y;
  34         int sign;
  35 
  36         sign = 1;
  37         x.len = y.len = 0;
  38         _mp_move(a, &x);
  39         _mp_move(b, &y);
  40         if (x.len < 0) {
  41                 sign = -1;
  42                 x.len = -x.len;
  43         }
  44         if (y.len < 0) {
  45                 sign = -sign;
  46                 y.len = -y.len;
  47         }
  48         _mp_xfree(q);
  49         _mp_xfree(r);
  50         m_div(&x, &y, q, r);
  51         if (sign == -1) {
  52                 q->len = -q->len;
  53                 r->len = -r->len;
  54         }
  55         _mp_xfree(&x);
  56         _mp_xfree(&y);
  57 }
  58 
  59 static int
  60 m_dsb(int qx, int n, short *a, short *b)
  61 {
  62         int borrow;
  63         int s3b2shit;
  64         int j;
  65         short fifteen = 15;
  66         short *aptr, *bptr;
  67 #ifdef DEBUGDSB
  68         (void) printf("m_dsb %d %d %d %d\n", qx, n, *a, *b);
  69 #endif
  70 
  71         borrow = 0;
  72         aptr = a;
  73         bptr = b;
  74         for (j = n; j > 0; j--) {
  75 #ifdef DEBUGDSB
  76                 (void) printf("1 borrow=%x %d %d %d\n", borrow, (*aptr * qx),
  77                     *bptr, *aptr);
  78 #endif
  79                 borrow -= (*aptr++) * qx - *bptr;
  80 #ifdef DEBUGDSB
  81                 (void) printf("2 borrow=%x %d %d %d\n", borrow, (*aptr * qx),
  82                     *bptr, *aptr);
  83 #endif
  84                 *bptr++ = (short)(borrow & 077777);
  85 #ifdef DEBUGDSB
  86                 (void) printf("3 borrow=%x %d %d %d\n", borrow, (*aptr * qx),
  87                     *bptr, *aptr);
  88 #endif
  89                 if (borrow >= 0) borrow >>= fifteen; /* 3b2 */
  90                 else borrow = 0xfffe0000 | (borrow >> fifteen);
  91 #ifdef DEBUGDSB
  92                 (void) printf("4 borrow=%x %d %d %d\n", borrow, (*aptr * qx),
  93                     *bptr, *aptr);
  94 #endif
  95         }
  96         borrow += *bptr;
  97         *bptr = (short)(borrow & 077777);
  98                 if (borrow >= 0) s3b2shit = borrow >> fifteen; /* 3b2 */
  99                 else s3b2shit = 0xfffe0000 | (borrow >> fifteen);
 100         if (s3b2shit == 0) {
 101 #ifdef DEBUGDSB
 102         (void) printf("mdsb 0\n");
 103 #endif
 104                 return (0);
 105         }
 106         borrow = 0;
 107         aptr = a;
 108         bptr = b;
 109         for (j = n; j > 0; j--) {
 110                 borrow += *aptr++ + *bptr;
 111                 *bptr++ = (short)(borrow & 077777);
 112                 if (borrow >= 0) borrow >>= fifteen; /* 3b2 */
 113                 else borrow = 0xfffe0000 | (borrow >>fifteen);
 114         }
 115 #ifdef DEBUGDSB
 116         (void) printf("mdsb 1\n");
 117 #endif
 118         return (1);
 119 }
 120 
 121 static int
 122 m_trq(short v1, short v2, short u1, short u2, short u3)
 123 {
 124         short d;
 125         int x1;
 126         int c1;
 127 
 128         c1 = u1 * 0100000 + u2;
 129         if (u1 == v1) {
 130                 d = 077777;
 131         } else {
 132                 d = (short)(c1 / v1);
 133         }
 134         do {
 135                 x1 = c1 - v1 * d;
 136                 x1 = x1 * 0100000 + u3 - v2 * d;
 137                 --d;
 138         } while (x1 < 0);
 139 #ifdef DEBUGMTRQ
 140         (void) printf("mtrq %d %d %d %d %d %d\n", v1, v2, u1, u2, u3, (d+1));
 141 #endif
 142         return ((int)d + 1);
 143 }
 144 
 145 static void
 146 m_div(MINT *a, MINT *b, MINT *q, MINT *r)
 147 {
 148         MINT u, v, x, w;
 149         short d;
 150         short *qval;
 151         short *uval;
 152         int j;
 153         int qq;
 154         int n;
 155         short v1;
 156         short v2;
 157 
 158         u.len = v.len = x.len = w.len = 0;
 159         if (b->len == 0) {
 160                 _mp_fatal("mdiv divide by zero");
 161                 return;
 162         }
 163         if (b->len == 1) {
 164                 r->val = _mp_xalloc(1, "m_div1");
 165                 mp_sdiv(a, b->val[0], q, r->val);
 166                 if (r->val[0] == 0) {
 167                         free(r->val);
 168                         r->len = 0;
 169                 } else {
 170                         r->len = 1;
 171                 }
 172                 return;
 173         }
 174         if (a -> len < b -> len) {
 175                 q->len = 0;
 176                 r->len = a->len;
 177                 r->val = _mp_xalloc(r->len, "m_div2");
 178                 for (qq = 0; qq < r->len; qq++) {
 179                         r->val[qq] = a->val[qq];
 180                 }
 181                 return;
 182         }
 183         x.len = 1;
 184         x.val = &d;
 185         n = b->len;
 186         d = 0100000 / (b->val[n - 1] + 1);
 187         mp_mult(a, &x, &u); /* subtle: relies on mult allocing extra space */
 188         mp_mult(b, &x, &v);
 189 #ifdef DEBUG_MDIV
 190         (void) printf("  u=%s\n", mtox(&u));
 191         (void) printf("  v=%s\n", mtox(&v));
 192 #endif
 193         v1 = v.val[n - 1];
 194         v2 = v.val[n - 2];
 195         qval = _mp_xalloc(a -> len - n + 1, "m_div3");
 196         uval = u.val;
 197         for (j = a->len - n; j >= 0; j--) {
 198                 qq = m_trq(v1, v2, uval[j + n], uval[j + n - 1],
 199                                                         uval[j + n - 2]);
 200                 if (m_dsb(qq, n, v.val, uval + j))
 201                         qq -= 1;
 202                 qval[j] = (short)qq;
 203         }
 204         x.len = n;
 205         x.val = u.val;
 206         _mp_mcan(&x);
 207 #ifdef DEBUG_MDIV
 208         (void) printf("  x=%s\n", mtox(&x));
 209         (void) printf("  d(in)=%d\n", (d));
 210 #endif
 211         mp_sdiv(&x, d, &w, &d);
 212 #ifdef DEBUG_MDIV
 213         (void) printf("  w=%s\n", mtox(&w));
 214         (void) printf("  d(out)=%d\n", (d));
 215 #endif
 216         r->len = w.len;
 217         r->val = w.val;
 218         q->val = qval;
 219         qq = a->len - n + 1;
 220         if (qq > 0 && qval[qq - 1] == 0)
 221                 qq -= 1;
 222         q->len = qq;
 223         if (qq == 0)
 224                 free(qval);
 225         if (x.len != 0)
 226                 _mp_xfree(&u);
 227         _mp_xfree(&v);
 228 }