#ident "@(#)bcddiv.c	1.4 5/24/96 11:29:56"
/*
/* Copyright John Moyer 1996
/* permission is granted to use this for any purpose provided proper
/* credit is given to the author
*/

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <math.h>


#include "bignum.h"

#ifdef DEBUG
void err_prt(char *s, BigNum *x)
{
char str[ISIZE+8];
bcd2ascii(str, sizeof(str), x);
fprintf(stderr,"%s%s\n",s,str);
}
#endif

/* divide x1 by y1 and return remainder in r1 and quotient in q1 */
int bcddiv(BigNum *x1, BigNum *y1, BigNum *r1, BigNum *q1)
{
int i, j, k, err;
char str[ISIZE+8];
BigNum x2, t, t2;

/* ascii2bcd("0",q1); */
int2bcd(0,q1);
int2bcd(0,&t);

if ( y1->c > x1->c )
  {
/*  r1->isign = 1; */
  *r1 = *x1;   /* remainder */
  return 0;
  }

x2 = *x1;
x2.isign = 1;
while ( x2.c - y1->c > 1 )
  {
  int2bcd(0,&t);
  t.c = (x2.c - y1->c );	/* how many times ten */
  t.x[(x2.c - y1->c )-1] = 1;
  t.isign = 1;
  t2 = *q1;
  addbignum(&t,&t2,q1);

  /* quotient is now some integer times 10 */
#ifdef DEBUG
  err_prt("\nq1=",q1);
  fprintf(stderr,"x2.c=%d,y1->c=%d\n",x2.c,y1->c);
  err_prt("amount added to quotient t=",&t);
#endif
  int2bcd(0,&t2);
  bcdmul(y1->x, t.x, t2.x, y1->c, t.c);
  for ( t2.c = 0, k = ISIZE -1 ; k >= 0; k-- )
    {
    if ( t2.x[k] != 0 )
      {
      t2.c = k+1;
      break;
      }
    }
  t2.isign = 1;
  /* t2 is partial quotient times y1 */
  int2bcd(0,r1);
#ifdef DEBUG
  err_prt("y1*t t2=",&t2);
#endif
  r1->isign = bcdsub(x2.x,t2.x,r1->x,x2.c);
  for ( r1->c = 0, j = ISIZE -1 ; j >= 0; j-- )
    if ( r1->x[j] != 0 )
      {
      r1->c = j+1;
      break;
      }
  x2 = *r1;
#ifdef DEBUG
  err_prt("x2-=t2 x2=",&x2);
#endif
  }
for ( i = 0; i < ISIZE *10; i++ )
  {
  int2bcd(0,r1);
  if ( x2.c >= y1->c )
    {
    r1->isign = bcdsub(x2.x,y1->x,r1->x,x2.c);
    }
  else
    {
    r1->isign = bcdsub(x2.x,y1->x,r1->x,y1->c);
    }

  if ( r1->isign == 15 )
    {
    *r1 = x2;	/* remainder */
    break;
    }
  else
    {
    for ( r1->c = 0, j = ISIZE -1 ; j >= 0; j-- )
      if ( r1->x[j] != 0 )
        {
        r1->c = j+1;
        break;
        }
    x2 = *r1;
    if ( q1->c >= 1 )
      j = q1->c;
    else
      j = 1;
    bcdinc(q1->x,j);
    for ( q1->c = 0, j = ISIZE -1 ; j >= 0; j-- )
      if ( q1->x[j] != 0 )
        {
        q1->c = j+1;
        break;
        }
    if ( r1->c == 0 )
      break;	/* remainder is zero so we are done */
    }
  }
r1->isign = 1;
if ( x1->isign == y1->isign )
  q1->isign = 1;
else
  q1->isign = -1;
return (0);
}
