Jens Rohler: prevent negative numbers
[infodrom/dtaus] / bigint.c
index 99fc7b0..61eefd4 100644 (file)
--- a/bigint.c
+++ b/bigint.c
@@ -46,8 +46,50 @@ bigint bigint_add(bigint a, bigint b)
 
 bigint bigint_sub(bigint a, bigint b)
 {
-  /* FIXME */
-  fprintf (stderr, "bigint_sub not supported yet.\n");
+  unsigned long int tmp;
+  int t;
+  int i;
+  int cmp = bigint_cmp(a,b);
+  bigint rem = bigint_int(0);;
+
+  if (cmp == -1) {
+    fprintf(stderr, "Error in bigint_sub: result is negative.\n");
+    return bigint_int(0);
+  }
+  if (cmp == 0)
+    return bigint_int(0);
+
+  for (i=0;i<BIGINT_LEN;i++) {
+    if (a.val[i] >= b.val[i]) {
+      a.val[i] = a.val[i] - b.val[i];
+      continue;
+    }
+    tmp = b.val[i];
+    tmp = tmp - a.val[i];
+    a.val[i] = 0;
+    t = i;
+    while (1) {
+      if (t+1 >= BIGINT_LEN) {
+       fprintf(stderr, "Error in bigint_sub.\n");
+       return bigint_int(0);
+      }
+      if ( a.val[t+1] == 0 ) {
+       t++;
+       continue;
+      }
+      a.val[t+1] = a.val[t+1] - 1;
+      while(t >= 0) {
+       rem = bigint_add(rem, bigint_int(a.val[t]));
+       a.val[t] = BIGINT_MAX - 1;
+       t--;
+      }
+      a.val[i] = a.val[i] - tmp;
+      a = bigint_add(a, bigint_int(1));
+      a = bigint_add(a, rem);
+      break;
+    }
+  }
+  
   return a;
 }
 
@@ -56,6 +98,11 @@ bigint bigint_int(int num)
   bigint x;
   int i;
 
+  if (num < 0) {
+    fprintf(stderr, "Trying to assign negative value to bigint.\n");
+    num = 0;
+  }
+
   for (i=0; i<BIGINT_LEN; i++) x.val[i] = 0L;
   if (num < BIGINT_MAX)
     x.val[0] = num;
@@ -115,3 +162,19 @@ void bigint_sprintf (char *res, char *format, bigint a)
   }
   sprintf (res, format, s);
 }
+
+int bigint_cmp(bigint a, bigint b)
+{
+  int i;
+
+  for (i=BIGINT_LEN-1; i>=0; i--) {
+    if (a.val[i] > b.val[i])
+      return 1;
+    if (a.val[i] < b.val[i])
+      return -1;
+    if (a.val[i] == b.val[i])
+      continue;
+  }
+
+  return 0;
+}