#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 */