Corrected the bigint_int() routine with regards to large integers (as
[infodrom/dtaus] / bigint.c
1 /*
2     bigint.c - Manage big positive integer numbers
3     Copyright (c) 1996,2001,5  Martin Schulze <joey@infodrom.org>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19     $Id$
20  */
21
22 #include "bigint.h"
23 #include <stdio.h>
24 #include <string.h>
25 #include <malloc.h>
26
27 bigint bigint_add(bigint a, bigint b)
28 {
29   int i;
30   unsigned long int tmp;
31   bigint c;
32
33   for (i=0; i<BIGINT_LEN; i++) {
34     tmp = a.val[i] + b.val[i];
35     if (tmp >= BIGINT_MAX) {
36       c.val[i] = tmp - BIGINT_MAX;
37       if (i<BIGINT_LEN-1)
38         a.val[i+1]++;
39       else
40         fprintf(stderr, "Overflow in bigint addition.\n");
41     } else
42       c.val[i] = tmp;
43   }
44   return c;
45 }
46
47 bigint bigint_sub(bigint a, bigint b)
48 {
49   /* FIXME */
50   fprintf (stderr, "bigint_sub not supported yet.\n");
51   return a;
52 }
53
54 bigint bigint_int(int num)
55 {
56   bigint x;
57   int i;
58
59   for (i=0; i<BIGINT_LEN; i++) x.val[i] = 0L;
60   if (num < BIGINT_MAX)
61     x.val[0] = num;
62   else {
63     x.val[0] = num-BIGINT_MAX;
64     x.val[1] = num/BIGINT_MAX;
65   }
66
67   return x;
68 }
69
70 bigint bigint_string(char *s)
71 {
72   char tmp[BIGINT_PREC+1];
73   bigint a;
74   int i;
75   char *cp, *x;
76
77   for (i=0; i<BIGINT_LEN; i++) a.val[i] = 0L;
78   if ((x = (char *)malloc(strlen(s)+1))) {
79     strcpy(x, s);
80     for (i=0; i<BIGINT_LEN; i++) {
81       if (strlen(x)) {
82         cp = x;
83         if (strlen(x) > BIGINT_PREC)
84           cp += (strlen(x) - BIGINT_PREC);
85         strcpy(tmp, cp);
86         *cp = '\0';
87         sscanf(tmp, "%lu", &a.val[i]);
88       }
89     }
90     free (x);
91   }
92
93   return a;
94 }
95
96 void bigint_sprintf (char *res, char *format, bigint a)
97 {
98   char s[(BIGINT_PREC*BIGINT_LEN)+1];
99   char tmp[BIGINT_PREC+1];
100   char form[6];
101   int i, max;
102
103   memset (s, 0, sizeof(s));
104   sprintf(form, "%%0%dlu", BIGINT_PREC);
105   max = BIGINT_LEN;
106   for (;max>0 && !a.val[max-1];max--);
107   if (max == 0) s[0] = '0';
108   for (i=0; i<max; i++) {
109     if (i<max-1)
110       sprintf(tmp, form, a.val[i]);
111     else
112       sprintf(tmp, "%lu", a.val[i]);
113     sprintf (res, "%s%s", tmp, s);
114     sprintf (s, "%s", res);
115   }
116   sprintf (res, format, s);
117 }