[ create a new paste ] login | about

Link: http://codepad.org/0WrPn4ib    [ raw code | fork ]

C, pasted on Jan 24:
#include <stdio.h>
#include <assert.h>

#define N 5
#define BIT 15
#define MASK 0x7fff
#define BUFF10 30
#define SIGN(x) (((x) >> (BIT - 1)) ? 1 : 0)
typedef unsigned int uintN[N];

void shift_div(int *mod, uintN q)
{
  int cy, i;

  cy = 0;
  for (i = 0; i < N; i++) {
    q[i] = q[i] << 1;
    if (cy)
      q[i] = q[i] | 0x01;
    cy = (q[i] >> BIT);
    q[i] = q[i] & MASK;
  }
  *mod = *mod << 1;
  if (cy)
    *mod = *mod | 0x01;
}

void copy_uintN(uintN a, uintN b)
{
  int i;
  for (i = 0; i < N; i++)
    a[i] = b[i];
}

void clear_uintN(uintN n)
{
  int i;
  for (i = 0; i < N; i++)
    n[i] = 0;
}

void output2(uintN n)
{
  int i;
  unsigned int j;
  for (i = N - 1; i >= 0; --i) {
    for (j = 0x8000; j > 0; j = (j >> 1)) {
      putchar((n[i] & j) ? '1' : '0');
    }
    putchar(' ');
  }
  putchar('\n');
}

void div10(uintN n, uintN q, int *mod)
{
  int i;
  copy_uintN(q, n);
  *mod = 0;
  for (i = 0; i < N * BIT; i++) {
    shift_div(mod, q);
    if (*mod >= 10) {
      q[0] = q[0] | 0x01;
      *mod = *mod - 10;
    }
  }
}

int iszero_uintN(uintN n)
{
  int i;
  for (i = 0; i < N; i++)
    if (n[i] != 0)
      return 0;
  return 1;
}

void add_uintN(uintN c, uintN a, uintN b)
{
  int i, cy;
  unsigned int s;
  cy = 0;
  for (i = 0; i < N; i++) {
    s = a[i] + b[i] + cy;
    cy = ((s >> BIT) > 0) ? 1 : 0;
    c[i] = s & MASK;
  }
}

void sub_uintN(uintN c, uintN a, uintN b)
{
  int i, br;
  unsigned int s;
  br = 0;
  for (i = 0; i < N; i++) {
    s = a[i] - b[i] - br;
    br = ((s >> BIT ) > 0) ? 1 : 0;
    c[i] = s & MASK;
    
  }
}

void output10(uintN m)
{
  int mod10[BUFF10];
  uintN q, n;
  int i, mod;

  copy_uintN(n, m);
  for(i = 0;;) {
    div10(n, q, &mod);
    if (iszero_uintN(q) && mod == 0)
      break;
    mod10[i++] = mod;
    copy_uintN(n, q);
  }
  i--;
  if (i < 0) {
/*     printf("0\n"); */
    putchar('0');
    return;
  }
  for (;i >= 0; --i)
    putchar('0' + mod10[i]);
/*   putchar('\n'); */
}

void mul10(uintN n)
{
  int i;
  uintN tmp1;

  copy_uintN(tmp1, n);
  for (i = 0; i < 9; i++) {
    add_uintN(tmp1, tmp1, n);
  }
  copy_uintN(n, tmp1);
}  

void input10(uintN n, char *p)
{
  uintN tmp2;

  clear_uintN(n);
  for (;*p != '\0'; p++) {
    clear_uintN(tmp2);
    tmp2[0] = *p - '0';
    mul10(n);
    add_uintN(n, n, tmp2);
  }
}

int shift_mul(uintN n)
{
  int cy, i;

  cy = 0;
  for (i = 0; i < N; i++) {
    n[i] = n[i] << 1;
    if (cy)
      n[i] = n[i] | 0x01;
    cy = (n[i] >> BIT);
    n[i] = n[i] & MASK;
  }
  return cy;
}

void mul_uintN(uintN p, uintN a, uintN b)
{
  uintN s;
  int i, cy; 

  clear_uintN(p);
  clear_uintN(s);
  for (i = 0; i < N * BIT; i++) {
    cy = shift_mul(b);
    if (cy)
      add_uintN(s, p, a);
    if (i < N * BIT - 1)
      shift_mul(s);
    copy_uintN(p, s);
  }
}

int greater_uintN(uintN a, uintN b)
{
  uintN x, y;
  int cy1, cy2, i;
  copy_uintN(x, a);
  copy_uintN(y, b);
  i = 0;
  for(;;) {
    i++;
    if (i >= BIT * N)
      break;
    cy1 = shift_mul(x);
    cy2 = shift_mul(y);
    if (cy1 > cy2)
      return 1;
    if (cy1 < cy2)
      return -1;
  }
  return 0;
}

void div_uintN(uintN q, uintN a, uintN b)
{
  int i, cy;
  uintN mod, x;

  copy_uintN(x, a);
  clear_uintN(mod);
  for (i = 0; i < N * BIT; i++) {
    cy = shift_mul(x);
    if (cy)
      mod[0] = mod[0] | 0x01;
    if (greater_uintN(mod, b) >= 0) {
      x[0] = x[0] | 0x01;
      sub_uintN(mod, mod, b);
    }
    shift_mul(mod);
  }
  copy_uintN(q, x);
}

/*---------------------------------------------------------*/
int main(int argc, char *argv[])
{
  uintN a, b, c;
  char enzan;
  if (argc != 4) {
    fprintf(stderr, "usage: A + B or A * B\n");
    exit(-1);
  }
  switch (*argv[2]) {
  case '+':
    enzan = '+';
    break;
  case '*':
    enzan = '*';
    break;
  default:
    fprintf(stderr, "operator is '+' or '*'");
    break;
  }
  input10(a, argv[1]);
  input10(b, argv[3]);
  output10(a);
  printf(" %c ", (enzan == '+') ? '+' : '*');
  output10(b);
  if (enzan == '+')
    add_uintN(c, a, b);
  else if (enzan == '*')
    mul_uintN(c, a, b);
  printf(" = ");
  output10(c);
  return 0;
}
/* end */


Create a new paste based on this one


Comments: