1 /****************************************************************/
2 /* file aritools.c
3 
4 ARIBAS interpreter for Arithmetic
5 Copyright (C) 1996/2003 O.Forster
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 Address of the author
22 
23     Otto Forster
24     Math. Institut der LMU
25     Theresienstr. 39
26     D-80333 Muenchen, Germany
27 
28 Email   forster@mathematik.uni-muenchen.de
29 */
30 /****************************************************************/
31 /*
32 ** aritools.c
33 ** tools fuer bignum-Arithmetik
34 **
35 ** vorzeichenlose bignums werden als Paare (x,n) dargestellt,
36 ** wobei n eine ganze Zahl >= 0 und x ein Array (x[0],...,x[n-1])
37 ** von unsigned 16-bit-Zahlen ist; fuer die Zahl 0 ist n = 0,
38 ** sonst ist stets n > 0 und x[n-1] != 0
39 **
40 ** Rueckgabewert der Funktionen meist Laenge des Resultat-Arrays
41 **
42 ** Typen: word2 ist unsigned 16-bit-Zahl, word4 unsigned 32-bit-Zahl
43 */
44 /*-------------------------------------------------------------------*/
45 /*
46 ** date of last change
47 ** 1995-10-29:  modification of function biggcd
48 ** 1997-02-25:  more M_3264 support in multbig, divbig and modbig
49 ** 1999-06-03:  power for exponents a >= 2**16; return to old version of modbig
50 ** 2002-04-20:  modmultbig, addsarr
51 ** 2003-06-16:  modnegbig
52 ** 2003-11-09:  bugfix in function divbig
53 */
54 
55 #include "common.h"
56 
57 PUBLIC int shiftarr _((word2 *x, int n, int sh));
58 PUBLIC int lshiftarr    _((word2 *x, int n, long sh));
59 PUBLIC int addarr   _((word2 *x, int n, word2 *y, int m));
60 PUBLIC int subarr   _((word2 *x, int n, word2 *y, int m));
61 PUBLIC int sub1arr  _((word2 *x, int n, word2 *y, int m));
62 PUBLIC int addsarr  _((word2 *x, int n, int sign1,
63                 word2 *y, int m, int sing2, int *psign));
64 PUBLIC int multbig  _((word2 *x, int n, word2 *y, int m, word2 *z,
65                 word2 *hilf));
66 PUBLIC int divbig   _((word2 *x, int n, word2 *y, int m, word2 *quot,
67                 int *rlenptr, word2 *hilf));
68 PUBLIC int modbig   _((word2 *x, int n, word2 *y, int m, word2 *hilf));
69 PUBLIC int modnegbig    _((word2 *x, int n, word2 *y, int m, word2 *hilf));
70 PUBLIC int modmultbig   _((word2 *xx, int xlen, word2 *yy, int ylen,
71                 word2 *mm, int mlen, word2 *zz, word2 *hilf));
72 PUBLIC int multfix  _((int prec, word2 *x, int n, word2 *y, int m,
73                 word2 *z, word2 *hilf));
74 PUBLIC int divfix   _((int prec, word2 *x, int n, word2 *y, int m,
75                word2 *z, word2 *hilf));
76 PUBLIC unsigned shortgcd  _((unsigned x, unsigned y));
77 PUBLIC int biggcd   _((word2 *x, int n, word2 *y, int m, word2 *hilf));
78 PUBLIC int power    _((word2 *x, int n, unsigned a, word2 *p,
79                word2 *temp, word2 *hilf));
80 PUBLIC int bigsqrt  _((word2 *x, int n, word2 *z, int *rlenptr,
81                word2 *temp));
82 PUBLIC int lbitlen  _((word4 x));
83 PUBLIC int bcd2big  _((word2 *x, int n, word2 *y));
84 PUBLIC int str2int  _((char *str, int *panz));
85 PUBLIC int str2big  _((char *str, word2 *arr, word2 *hilf));
86 PUBLIC int bcd2str  _((word2 *arr, int n, char *str));
87 PUBLIC int big2xstr _((word2 *arr, int n, char *str));
88 PUBLIC int digval   _((int ch));
89 PUBLIC int xstr2big _((char *str, word2 *arr));
90 PUBLIC int ostr2big _((char *str, word2 *arr));
91 PUBLIC int bstr2big _((char *str, word2 *arr));
92 PUBLIC int nibdigit _((word2 *arr, int k));
93 PUBLIC int nibndigit    _((int n, word2 *arr, long k));
94 PUBLIC int nibascii _((word2 *arr, int k));
95 PUBLIC int hexascii _((int n));
96 PUBLIC int shiftbcd _((word2 *arr, int n, int k));
97 PUBLIC int incbcd   _((word2 *x, int n, unsigned a));
98 
99 /*-------------------------------------------------------------*/
100 PRIVATE int shlaux  _((word2 *x, int n, int k, int b));
101 PRIVATE int shraux  _((word2 *x, int n, int k, int b));
102 PRIVATE unsigned nibble _((unsigned x, int k));
103 PRIVATE int str2barr    _((char *str, int b, word2 *arr));
104 PRIVATE int nthbit  _((word2 *arr, long n));
105 
106 #define DECBASE 10000
107 /*-------------------------------------------------------------------*/
108 /*
109 ** Shift von (x,n) um sh bit-Stellen
110 ** sh > 0: Links-Shift; sh < 0: Rechts-Shift
111 ** arbeitet destruktiv auf x
112 ** x muss genuegend lang sein
113 */
shiftarr(x,n,sh)114 PUBLIC int shiftarr(x,n,sh)
115 word2 *x;
116 int n, sh;
117 {
118     int k, b;
119 
120     if(!n || !sh)
121         return(n);
122     k = (sh > 0 ? sh : -sh);
123     b = k & 0x000F;
124     k >>= 4;
125     if(sh > 0)
126         return(shlaux(x,n,k,b));
127     else
128         return(shraux(x,n,k,b));
129 }
130 /*-------------------------------------------------------------------*/
shlaux(x,n,k,b)131 PRIVATE int shlaux(x,n,k,b)
132 word2 *x;
133 int n,k,b;
134 {
135     cpyarr1(x,n,x+k);
136     n = k + shlarr(x+k,n,b);
137     setarr(x,k,0);
138     return(n);
139 }
140 /*-------------------------------------------------------------------*/
shraux(x,n,k,b)141 PRIVATE int shraux(x,n,k,b)
142 word2 *x;
143 int n,k,b;
144 {
145     if(k >= n)
146         return(0);
147     n -= k;
148     cpyarr(x+k,n,x);
149     return(shrarr(x,n,b));
150 }
151 /*-------------------------------------------------------------------*/
152 /*
153 ** Shift von (x,n) um sh bit-Stellen
154 ** sh ist long, aber abs(sh) >> 4 muss integer sein
155 ** sh > 0: Links-Shift; sh < 0: Rechts-Shift
156 ** arbeitet destruktiv auf x
157 ** x muss genuegend lang sein
158 */
lshiftarr(x,n,sh)159 PUBLIC int lshiftarr(x,n,sh)
160 word2 *x;
161 int n;
162 long sh;
163 {
164     int k, b;
165     word4 a;
166 
167     if(!n || !sh)
168         return(n);
169     a = (sh > 0 ? sh : -sh);
170     k = a >> 4;
171     b = a & 0x0000000F;
172     if(sh > 0)
173         return(shlaux(x,n,k,b));
174     else
175         return(shraux(x,n,k,b));
176 }
177 /*-------------------------------------------------------------------*/
178 /*
179 ** x := (x,n) + (y,m)
180 */
addarr(x,n,y,m)181 PUBLIC int addarr(x,n,y,m)
182 word2 *x, *y;
183 int n, m;
184 {
185     int k;
186 
187     if(n < m) {
188         cpyarr(y+n,m-n,x+n);
189         k = m;          /* swap m, n */
190         m = n;
191         n = k;
192     }
193     if(sumarr(x,m,y))
194         n = m + incarr(x+m,n-m,1);
195     return(n);
196 }
197 /*-------------------------------------------------------------------*/
198 /*
199 ** x := (x,n) - (y,m)
200 ** setzt voraus, dass (x,n) >= (y,m)
201 */
subarr(x,n,y,m)202 PUBLIC int subarr(x,n,y,m)
203 word2 *x, *y;
204 int n, m;
205 {
206     if(diffarr(x,m,y))
207         n = m + decarr(x+m,n-m,1);
208     while(n > 0 && x[n-1] == 0)
209         n--;
210     return(n);
211 }
212 /*-------------------------------------------------------------------*/
213 /*
214 ** x := -(x,n) + (y,m)
215 ** setzt voraus, dass (y,m) >= (x,n)
216 */
sub1arr(x,n,y,m)217 PUBLIC int sub1arr(x,n,y,m)
218 word2 *x, *y;
219 int n, m;
220 {
221     if(n < m)
222         cpyarr(y+n,m-n,x+n);
223     if(diff1arr(x,n,y))
224         m = n + decarr(x+n,m-n,1);
225     while(m > 0 && x[m-1] == 0)
226         m--;
227     return(m);
228 }
229 /*-------------------------------------------------------------------*/
230 /*
231 ** Addition of signed bigintegers
232 ** non-negative numbers: sign = 0;
233 ** negative numbers:     sign = MINUSBYTE;
234 **
235 ** array x is overwritten with the result; must be long enough
236 ** sign of result in *psign
237 */
addsarr(x,n,sign1,y,m,sign2,psign)238 PUBLIC int addsarr(x,n,sign1,y,m,sign2,psign)
239 word2 *x, *y;
240 int sign1, sign2;
241 int *psign;
242 {
243     int k;
244     int cmp;
245 
246     if(sign1 == sign2) {
247         *psign = sign1;
248         if(n < m) {
249             cpyarr(y+n,m-n,x+n);
250             k = m;          /* swap m, n */
251             m = n;
252             n = k;
253         }
254         if(sumarr(x,m,y))
255             n = m + incarr(x+m,n-m,1);
256         return(n);
257     }
258     /* else */
259     cmp = cmparr(x,n,y,m);
260     if(cmp > 0) {
261         *psign = sign1;
262         if(diffarr(x,m,y))
263             n = m + decarr(x+m,n-m,1);
264         while(n > 0 && x[n-1] == 0)
265             n--;
266         return(n);
267     }
268     else if(cmp < 0) {
269         *psign = sign2;
270         if(n < m)
271             cpyarr(y+n,m-n,x+n);
272         if(diff1arr(x,n,y))
273             m = n + decarr(x+n,m-n,1);
274         while(m > 0 && x[m-1] == 0)
275             m--;
276         return(m);
277     }
278     else {
279         *psign = 0;
280         return 0;
281     }
282 }
283 /*-------------------------------------------------------------------*/
284 /*
285 ** z := (x,n) * (y,m)
286 ** Rueckgabewert Laenge von z
287 ** hilf ist Platz fuer Hilfsvariable;
288 ** muss mindestens max(n,m) + 2 lang sein
289 */
multbig(x,n,y,m,z,hilf)290 PUBLIC int multbig(x,n,y,m,z,hilf)
291 word2 *x, *y, *z, *hilf;
292 int n, m;
293 {
294     int hilflen, zlen;
295     word4 u;
296 
297     if(!n || !m)
298         return(0);
299     if(m == 1)
300         return(multarr(x,n,(unsigned)*y,z));
301     else if(n == 1)
302         return(multarr(y,m,(unsigned)*x,z));
303 #ifdef M_3264
304     else if(m == 2) {
305         u = big2long(y,2);
306         return(mult4arr(x,n,u,z));
307     }
308     else if(n == 2) {
309         u = big2long(x,2);
310         return(mult4arr(y,m,u,z));
311     }
312     setarr(z,m-1,0);
313     if(m & 1) {
314         y += m-1;
315         z += m-1;
316         zlen = multarr(x,n,(unsigned)*y,z);
317     }
318     else {
319         y += m;
320         z += m;
321         zlen = -2;
322     }
323     while(m >= 2) {
324         m -= 2;
325         z -= 2;
326         zlen += 2;
327         u = *--y;
328         u <<= 16;
329         u += *--y;
330         hilflen = mult4arr(x,n,u,hilf);
331         zlen = addarr(z,zlen,hilf,hilflen);
332     }
333     return(zlen);
334 #else
335     setarr(z,m-1,0);
336     y += m;
337     z += m;
338     zlen = -1;
339     while(--m >= 0) {
340         hilflen = multarr(x,n,(unsigned)*--y,hilf);
341         zlen = addarr(--z,++zlen,hilf,hilflen);
342     }
343     return(zlen);
344 #endif
345 }
346 /*-------------------------------------------------------------------*/
347 /*
348 ** Ersetzt (x,n) destruktiv durch (x,n) mod (y,m)
349 */
modbig(x,n,y,m,hilf)350 PUBLIC int modbig(x,n,y,m,hilf)
351 word2 *x, *y, *hilf;
352 int n, m;
353 {
354     word4 u, v;
355     unsigned a;
356     int cmp, b, b1;
357     int k, hilflen;
358 
359     if(!m)      /* Division durch 0 ohne Fehlermeldung */
360         return(0);
361     if(m == 1) {
362         a = y[0];
363         a = modarr(x,n,a);
364         *x = a;
365         return(a ? 1 : 0);
366     }
367 #ifdef M_3264
368     if(m == 2) {
369         u = big2long(y,m);
370         v = mod4arr(x,n,u);
371         k = long2big(v,x);
372         return(k);
373     }
374 #endif
375     k = n - m;
376     if(k >= 0)
377         cmp = cmparr(x+k,n-k,y,m);
378     if(k < 0 || (k == 0 && cmp < 0))
379         return(n);      /* (y,m) > (x,n) */
380     else if(k > 0 && cmp < 0)
381         k--;
382 
383     b = bitlen(y[m-1]);
384     b1 = 16 - b;
385     v = (y[m-1] << b1) + (y[m-2] >> b);
386     u = 0xFFFFFFFF;
387     u /= (v + 1);
388 
389     k++;
390     x += k;
391     n -= k;
392     while(--k >= 0) {
393         --x;
394         if(n || *x)
395             n++;
396         if(n >= m) {
397             v = (x[m-1] >> b);
398             if(n > m)   /* dann n = m+1 */
399                 v += (x[m] << b1);
400             a = (u*v) >> 16;
401             hilflen = multarr(y,m,a,hilf);
402             n = subarr(x,n,hilf,hilflen);
403             while(cmparr(x,n,y,m) >= 0)
404                 n = subarr(x,n,y,m);
405         }
406     }
407     return(n);
408 }
409 /*-------------------------------------------------------------------*/
410 /*
411 ** Ersetzt (x,n) destruktiv durch -(x,n) mod (y,m)
412 */
modnegbig(x,n,y,m,hilf)413 PUBLIC int modnegbig(x,n,y,m,hilf)
414 word2 *x, *y, *hilf;
415 int n, m;
416 {
417     int cmp;
418 
419     cmp = cmparr(y,m,x,n);
420     if(cmp == 0)
421         n = 0;
422     else if(cmp < 0)
423         n = modbig(x,n,y,m,hilf);
424     if(n > 0)
425         return sub1arr(x,n,y,m);
426     else
427         return 0;
428 }
429 /*-------------------------------------------------------------------*/
430 /*
431 ** (zz,ret) = (xx,xlen)*(yy,ylen) mod (mm,mlen)
432 ** TODO: optimize!
433 */
modmultbig(xx,xlen,yy,ylen,mm,mlen,zz,hilf)434 PUBLIC int modmultbig(xx,xlen,yy,ylen,mm,mlen,zz,hilf)
435 word2 *xx,*yy,*mm,*zz,*hilf;
436 int xlen, ylen, mlen;
437 {
438     int len;
439 
440     len = multbig(xx,xlen,yy,ylen,zz,hilf);
441     len = modbig(zz,len,mm,mlen,hilf);
442     return len;
443 }
444 /*-------------------------------------------------------------------*/
445 #ifdef OLDVERSION
446 /*
447 ** quot = (x,n) / (y,m); Voraussetzung (y,m) != null
448 ** Arbeitet destruktiv auf x; x wird rest, seine Laenge in *rlenptr
449 ** hilf ist Platz fuer Hilfsvariable; muss mindestens m+1 lang sein
450 ** Funktioniert fuer Bestimmung des Restes auch, falls
451 ** Platz quot und Platz hilf gleich sind und der Quotient
452 ** nicht interessiert
453 */
divbig(x,n,y,m,quot,rlenptr,hilf)454 PUBLIC int divbig(x,n,y,m,quot,rlenptr,hilf)
455 word2 *x, *y, *quot, *hilf;
456 int n, m, *rlenptr;
457 {
458     word4 u, v;
459     word2 a;
460     int k, quotlen, hilflen;
461     int cmp, b, b1;
462 
463     if(!m) {    /* Division durch 0 ohne Fehlermeldung */
464         *rlenptr = 0;
465         return(0);
466     }
467     if(m == 1) {
468         quotlen = divarr(x,n,(unsigned)y[0],&a);
469         cpyarr(x,quotlen,quot);
470         *x = a;
471         *rlenptr = (a ? 1 : 0);
472         return(quotlen);
473     }
474 #ifdef M_3264
475     if(m == 2) {
476         u = big2long(y,m);
477         quotlen = div4arr(x,n,u,&v);
478         cpyarr(x,quotlen,quot);
479         *rlenptr = long2big(v,x);
480         return(quotlen);
481     }
482 #endif
483     k = n - m;
484     if(k >= 0)
485         cmp = cmparr(x+k,n-k,y,m);
486     if(k < 0 || (k == 0 && cmp < 0)) {
487         *rlenptr = n;
488         return(0);
489     }
490     else if(k > 0 && cmp < 0)
491         k--;
492 
493     b = bitlen(y[m-1]);
494     b1 = 16 - b;
495     v = (y[m-1] << b1) + (y[m-2] >> b);
496     u = 0xFFFFFFFF;
497     u /= (v + 1);
498 
499     k++;
500     x += k;
501     n -= k;
502     quot += k;
503     quotlen = k;
504     while(--k >= 0) {
505         --x;
506         if(n || *x)
507             n++;
508         if(n >= m) {
509             v = (x[m-1] >> b);
510             if(n > m)   /* dann n = m+1 */
511                 v += (x[m] << b1);
512             a = (u*v) >> 16;
513             hilflen = multarr(y,m,a,hilf);
514             n = subarr(x,n,hilf,hilflen);
515             while(cmparr(x,n,y,m) >= 0) {
516                 a++;
517                 n = subarr(x,n,y,m);
518             }
519         }
520         else
521             a = 0;
522         *--quot = a;
523     }
524     *rlenptr = n;
525     return(quotlen);
526 }
527 /*-------------------------------------------------------------------*/
528 #else /* NEWVERSION */
529 /*
530 ** quot = (x,n) / (y,m); Voraussetzung (y,m) != null
531 ** Arbeitet destruktiv auf x; x wird rest, seine Laenge in *rlenptr
532 ** hilf ist Platz fuer Hilfsvariable; muss mindestens m+1 lang sein
533 ** Funktioniert fuer Bestimmung des Restes auch, falls
534 ** Platz quot und Platz hilf gleich sind und der Quotient
535 ** nicht interessiert
536 */
divbig(x,n,y,m,quot,rlenptr,hilf)537 PUBLIC int divbig(x,n,y,m,quot,rlenptr,hilf)
538 word2 *x, *y, *quot, *hilf;
539 int n, m, *rlenptr;
540 {
541     word4 u, v;
542     word2 a;
543     int k, quotlen, hilflen;
544     int cmp, b, b1;
545 #ifdef M_3264
546     int kappa, nu, mu;
547     word2 ww[6];
548 #endif
549 
550     if(!m) {    /* Division durch 0 ohne Fehlermeldung */
551         *rlenptr = 0;
552         return(0);
553     }
554     if(m == 1) {
555         quotlen = divarr(x,n,(unsigned)y[0],&a);
556         cpyarr(x,quotlen,quot);
557         *x = a;
558         *rlenptr = (a ? 1 : 0);
559         return(quotlen);
560     }
561 #ifdef M_3264
562     if(m == 2) {
563         u = big2long(y,m);
564         quotlen = div4arr(x,n,u,&v);
565         cpyarr(x,quotlen,quot);
566         *rlenptr = long2big(v,x);
567         return(quotlen);
568     }
569 
570     /* else if(m >= 3) */
571     k = n - m;
572     if(k & 1) k++;      /* k must be even */
573     if(k >= 0)
574         cmp = cmparr(x+k,n-k,y,m);
575     if(k < 0 || (k == 0 && cmp < 0)) {     /* (y,m) > (x,n) */
576         *rlenptr = n;
577         return(0);
578     }
579     else if(cmp >= 0)
580         k += 2;
581     /* now k >= 2 and (x+k,n-k) < (y,m) */
582     b = bitlen(y[m-1]);
583     b1 = 16 - b;
584 
585     v = y[m-1]; v <<= 16;
586     v += y[m-2]; v <<= b1;
587     v += (y[m-3] >> b);
588     if(v < 0xFFFFFFFF)
589         v++;
590     ww[3] = 0x7FFF; ww[2] = 0xFFFF; ww[1] = 0xFFFF;
591     /* don't care for ww[0] */
592     nu = div4arr(ww,4,v,&u);
593     v = big2long(ww,nu);
594 
595     b--;
596     for(kappa = k-2; kappa >= 0; kappa -= 2) {
597         mu = m + kappa - 1;
598         if(n <= mu) {
599             quot[kappa] = quot[kappa+1] = 0;
600             continue;
601         }
602         nu = n - mu;
603         cpyarr(x+mu,nu,ww);
604         nu = mult4arr(ww,nu,v,ww);
605         nu = shrarr(ww+2,nu-2,b);
606         u = big2long(ww+2,nu);
607         hilflen = mult4arr(y,m,u,hilf);
608         n = subarr(x+kappa,n-kappa,hilf,hilflen);
609         while(cmparr(x+kappa,n,y,m) >= 0) {
610             u++;
611             n = subarr(x+kappa,n,y,m);
612         }
613         quot[kappa] = (word2)u;
614         quot[kappa+1] = (word2)(u >> 16);
615         if(n == 0) {
616             n = kappa;
617             while(n > 0 && !x[n-1])
618                 n--;
619         }
620         else
621             n += kappa;
622     }
623     *rlenptr = n;
624     if(quot[k-1])
625         quotlen = k;
626     else if(quot[k-2])
627         quotlen = k - 1;
628     else
629         quotlen = k - 2;
630 
631     return(quotlen);
632 #else
633     k = n - m;
634     if(k >= 0)
635         cmp = cmparr(x+k,n-k,y,m);
636     if(k < 0 || (k == 0 && cmp < 0)) {
637         *rlenptr = n;
638         return(0);
639     }
640     else if(k > 0 && cmp < 0)
641         k--;
642 
643     b = bitlen(y[m-1]);
644     b1 = 16 - b;
645     v = (y[m-1] << b1) + (y[m-2] >> b);
646     u = 0xFFFFFFFF;
647     u /= (v + 1);
648 
649     k++;
650     x += k;
651     n -= k;
652     quot += k;
653     quotlen = k;
654     while(--k >= 0) {
655         --x;
656         if(n || *x)
657             n++;
658         if(n >= m) {
659             v = (x[m-1] >> b);
660             if(n > m)   /* dann n = m+1 */
661                 v += (x[m] << b1);
662             a = (u*v) >> 16;
663             hilflen = multarr(y,m,a,hilf);
664             n = subarr(x,n,hilf,hilflen);
665             while(cmparr(x,n,y,m) >= 0) {
666                 a++;
667                 n = subarr(x,n,y,m);
668             }
669         }
670         else
671             a = 0;
672         *--quot = a;
673     }
674     *rlenptr = n;
675     return(quotlen);
676 #endif
677 }
678 #endif /* ?OLDVERSION */
679 /*-------------------------------------------------------------------*/
680 /*
681 ** Berechnet Produkt von (x,n)*(2^16)^-prec mit (y,m)*(2^16)^-prec
682 ** Ist len der Rueckgabewert so erhaelt man
683 **  Ergebnis = (z,len)*(2^16)^-prec
684 ** Platz z muss Laenge len + prec haben
685 ** Platz hilf muss Laenge m + 1 haben
686 */
multfix(prec,x,n,y,m,z,hilf)687 PUBLIC int multfix(prec,x,n,y,m,z,hilf)
688 int prec, n, m;
689 word2 *x, *y, *z, *hilf;
690 {
691     int len;
692 
693     if(n+m < prec || !n || !m)
694         return(0);
695     len = multbig(x,n,y,m,z,hilf) - prec;
696     if(len <= 0)
697         return(0);
698     else {
699         cpyarr(z+prec,len,z);
700         return(len);
701     }
702 }
703 /*-------------------------------------------------------------------*/
704 /*
705 ** Berechnet Quotient von (x,n)*(2^16)^-prec und (y,m)*(2^16)^-prec
706 ** Ist len der Rueckgabewert so erhaelt man
707 **  Ergebnis = (z,len)*(2^16)^-prec
708 ** Platz z muss Laenge len + 1 haben
709 ** Platz hilf muss Laenge n + m + prec + 1 haben
710 */
divfix(prec,x,n,y,m,z,hilf)711 PUBLIC int divfix(prec,x,n,y,m,z,hilf)
712 int prec, n, m;
713 word2 *x, *y, *z, *hilf;
714 {
715     int i, len;
716     word2 *temp;
717 
718     temp = hilf;
719     hilf += prec + n;
720     setarr(temp,prec,0);
721     cpyarr(x,n,temp+prec);
722     len = divbig(temp,prec+n,y,m,z,&i,hilf);
723     return(len);
724 }
725 /*------------------------------------------------------------------*/
shortgcd(x,y)726 PUBLIC unsigned shortgcd(x,y)
727 unsigned x, y;
728 {
729     unsigned r;
730 
731     while(y) {
732         r = x % y;
733         x = y;
734         y = r;
735     }
736     return(x);
737 }
738 /*------------------------------------------------------------------*/
739 /*
740 ** bestimmt den gcd von (x,n) und (y,m), Resultat in x
741 ** arbeitet destruktiv auf x und y
742 */
biggcd(x,n,y,m,hilf)743 PUBLIC int biggcd(x,n,y,m,hilf)
744 word2 *x, *y, *hilf;
745 int n, m;
746 {
747     int rlen;
748     word2 *savex, *temp;
749 
750     savex = x;
751 
752     while(m > 0) {
753         rlen = modbig(x,n,y,m,hilf);
754         temp = x;
755         x = y;
756         n = m;
757         y = temp;
758         m = rlen;
759     }
760     if(savex != x)
761         cpyarr(x,n,savex);
762     return(n);
763 }
764 /*-------------------------------------------------------------------*/
765 /*
766 ** p = (x,n) hoch a
767 ** temp und hilf sind Plaetze fuer Hilfsvariable,
768 ** muessen so gross wie das Resultat p sein
769 */
power(x,n,a,p,temp,hilf)770 PUBLIC int power(x,n,a,p,temp,hilf)
771 word2 *x, *p, *temp, *hilf;
772 int n;
773 unsigned a;
774 {
775     int plen;
776     unsigned mask, b;
777 
778     if(a == 0) {
779         p[0] = 1;
780         return(1);
781     }
782     else if(n == 0)
783         return(0);
784 
785     cpyarr(x,n,p);
786     plen = n;
787     if((b = (a >> 16))) {
788         mask = 0x8000;
789         mask <<= bitlen(b);
790     }
791     else {
792         mask = 1 << (bitlen(a)-1);
793     }
794     while(mask >>= 1) {
795         plen = multbig(p,plen,p,plen,temp,hilf);
796         if(a & mask) {
797             plen = multbig(temp,plen,x,n,p,hilf);
798         }
799         else
800             cpyarr(temp,plen,p);
801     }
802     return(plen);
803 }
804 /*-------------------------------------------------------------------*/
805 /*
806 ** Berechnet groesste ganze Zahl z mit z*z <= x
807 ** Arbeitet destruktiv auf x, x wird rest, seine Laenge in *rlenp
808 ** Platz x muss mindestens n+1 lang sein,
809 ** Platz z um eins groesser als die Wurzel,
810 ** Platz temp um 2 groesser als die Wurzel
811 */
bigsqrt(x,n,z,rlenp,temp)812 PUBLIC int bigsqrt(x,n,z,rlenp,temp)
813 word2 *x, *z, *temp;
814 int n;
815 int *rlenp;
816 {
817     int sh, len, restlen, templen;
818     word4 v, vv, rr;
819     unsigned xi;
820 
821     if(n <= 2) {
822         v = big2long(x,n);
823         v = intsqrt(v);
824         return(long2big(v,z));
825     }
826     sh = (n&1 ? 8 : 0);
827     sh += (16 - bitlen(x[n-1])) >> 1;
828     n = shiftarr(x,n,sh+sh);    /* n is always even */
829     x += n - 2;
830     rr = big2long(x,2);
831     v = intsqrt(rr);
832     restlen = long2big(rr-v*v,x);
833     len = n >> 1;
834     setarr(z,len-1,0);
835     z += len - 1;
836     z[0] = v;
837     n = incarr(z,1,(unsigned)v);
838     vv = v << 16;
839     while(--len > 0) {
840         z--;
841         n++;
842         x -= 2;
843         restlen += 2;
844         if(restlen == 2) {
845             while(restlen > 0 && x[restlen-1] == 0)
846                 restlen--;
847         }
848         if(restlen < n)
849             continue;
850         rr = big2long(x+n-2,2) >> 1;
851         if(restlen > n)     /* dann x[restlen-1] = 1 */
852             rr += 0x80000000;
853         if(rr >= vv)
854             xi = 0xFFFF;
855         else
856             xi = rr / v;
857         n = incarr(z,n,xi);
858         templen = multarr(z,n,xi,temp);
859         n = incarr(z,n,xi);
860         while(cmparr(x,restlen,temp,templen) < 0) {
861             n = decarr(z,n,1);
862             templen = subarr(temp,templen,z,n);
863             n = decarr(z,n,1);
864         }
865         restlen = subarr(x,restlen,temp,templen);
866         while(cmparr(x,restlen,z,n) > 0) {
867             n = incarr(z,n,1);
868             restlen = subarr(x,restlen,z,n);
869             n = incarr(z,n,1);
870         }
871     }
872     *rlenp = shiftarr(x,restlen,-sh-sh);
873     return(shiftarr(z,n,-sh-1));
874 }
875 /*-------------------------------------------------------------------*/
876 /*
877 ** bestimmt Laenge in Bits einer 32-Bit-Zahl x
878 ** 0 <= bitlen <= 32; bitlen = 0 <==> x == 0;
879 */
lbitlen(x)880 PUBLIC int lbitlen(x)
881 word4 x;
882 {
883     unsigned x0;
884 
885     if(x >= 0x10000) {
886         x0 = x >> 16;
887         return(16 + bitlen(x0));
888     }
889     else {
890         x0 = x;
891         return(bitlen(x0));
892     }
893 }
894 /*-------------------------------------------------------------------*/
895 /*
896 ** berechnet Nibble k (0 <= k <= 3) einer 16-Bit-Zahl x
897 */
nibble(x,k)898 PRIVATE unsigned nibble(x,k)
899 unsigned x;
900 int k;
901 {
902     k <<= 2;
903     x >>= k;
904 
905     return(x & 0x000F);
906 }
907 /*-------------------------------------------------------------------*/
908 /*
909 ** verwandelt Array von bcd-Zahlen (x,n) in big-Array y;
910 ** n ist Anzahl der word2-Stellen von x
911 ** Rueckgabewert Laenge von y.
912 */
bcd2big(x,n,y)913 PUBLIC int bcd2big(x,n,y)
914 word2 *x, *y;
915 int n;
916 {
917     int m;
918 
919     if(!n)
920         return(0);
921     x += n;
922     y[0] = bcd2int(*--x);
923     m = 1;
924     while(--n > 0) {
925         m = multarr(y,m,DECBASE,y);
926         m = incarr(y,m,bcd2int(*--x));
927     }
928     return(m);
929 }
930 /*-------------------------------------------------------------------*/
931 #ifdef NAUSKOMM
932 /********* not used *********/
933 /*
934 ** verwandelt String in Array von bcd-Zahlen;
935 ** Rueckgabewert Anzahl der Ziffern
936 */
str2bcd(str,arr)937 PRIVATE int str2bcd(str,arr)
938 char *str;
939 word2 *arr;
940 {
941     int n = str2barr(str,4,arr);
942 
943     return(n ? ((n-1)<<2) + niblen(arr[n-1]) : 0);
944 }
945 #endif
946 /*-------------------------------------------------------------------*/
str2int(str,panz)947 PUBLIC int str2int(str,panz)
948 char *str;
949 int *panz;
950 {
951     int i,x;
952     int ch;
953 
954     for(i=0,x=0; isdecdigit(ch = *str); i++,str++)
955         x = x * 10 + (ch - '0');
956     *panz = i;
957     return(x);
958 }
959 /*-------------------------------------------------------------------*/
960 /*
961 ** verwandelt String str in big-integer arr
962 ** Rueckgabewert Laenge von arr
963 ** Platz hilf muss strlen(str)/2 + 1 lang sein
964 */
str2big(str,arr,hilf)965 PUBLIC int str2big(str,arr,hilf)
966 char *str;
967 word2 *arr, *hilf;
968 {
969     int n;
970 
971     n = str2barr(str,4,hilf);
972     n = bcd2big(hilf,n,arr);
973     return(n);
974 }
975 /*-------------------------------------------------------------------*/
976 /*
977 ** verwandelt Array (arr,n) von bcd-Zahlen in String;
978 ** Rueckgabewert Stringlaenge
979 */
bcd2str(arr,n,str)980 PUBLIC int bcd2str(arr,n,str)
981 word2 *arr;
982 int n;
983 char *str;
984 {
985     int i = n;
986 
987     if(n == 0) {
988         *str++ = '0';
989         *str = 0;
990         return(1);
991     }
992     while(--i >= 0)
993         *str++ = nibascii(arr,i);
994     *str = 0;
995     return(n);
996 }
997 /*-------------------------------------------------------------------*/
big2xstr(arr,n,str)998 PUBLIC int big2xstr(arr,n,str)
999 word2 *arr;
1000 int n;
1001 char *str;
1002 {
1003     n = (n ? (n-1)*4 + niblen(arr[n-1]) : 0);
1004     return(bcd2str(arr,n,str));
1005 }
1006 /*-------------------------------------------------------------------*/
1007 /*
1008 ** ch muss ein hex-Character sein
1009 */
digval(ch)1010 PUBLIC int digval(ch)
1011 int ch;
1012 {
1013     if(ch >= '0' && ch <= '9')
1014         return(ch - '0');
1015     else if(ch >= 'A' && ch <= 'Z')
1016         return(ch - 'A' + 10);
1017     else
1018         return(ch - 'a' + 10);
1019 }
1020 /*-------------------------------------------------------------------*/
1021 /*
1022 */
str2barr(str,b,arr)1023 PRIVATE int str2barr(str,b,arr)
1024 char *str;
1025 int b;      /* bits per digit: 1=bin, 3=oct, 4=hex */
1026 word2 *arr;
1027 {
1028     int n, i, k, m, len = 0;
1029     unsigned dig;
1030 
1031     while(*str == '0')
1032         str++;
1033     while(*str++)
1034         len++;
1035     --str;      /* jetzt zeigt str auf '\0' */
1036     n = (len*b + 15) >> 4;
1037     setarr(arr,n,0);
1038     for(i=0; --len>=0; i+=b) {
1039         dig = digval(*--str);
1040         k = i >> 4;
1041         m = i & 0xF;
1042         arr[k] += (dig << m);
1043         if(m+b > 16)
1044             arr[k+1] += (dig >> (16-m));
1045     }
1046     return(n);
1047 }
1048 /*-------------------------------------------------------------------*/
1049 /*
1050 ** Verwandelt String in bignum (arr,n); n ist Rueckgabewert.
1051 */
xstr2big(str,arr)1052 PUBLIC int xstr2big(str,arr)
1053 char *str;
1054 word2 *arr;
1055 {
1056     return(str2barr(str,4,arr));
1057 }
1058 /*-------------------------------------------------------------------*/
ostr2big(str,arr)1059 PUBLIC int ostr2big(str,arr)
1060 char *str;
1061 word2 *arr;
1062 {
1063     return(str2barr(str,3,arr));
1064 }
1065 /*-------------------------------------------------------------------*/
bstr2big(str,arr)1066 PUBLIC int bstr2big(str,arr)
1067 char *str;
1068 word2 *arr;
1069 {
1070     return(str2barr(str,1,arr));
1071 }
1072 /*-------------------------------------------------------------------*/
1073 /*
1074 ** gibt k-te Dezimalstelle des bcd-Arrays arr;
1075 ** 0 <= k < Stellenzahl von arr
1076 */
nibdigit(arr,k)1077 PUBLIC int nibdigit(arr,k)
1078 word2 *arr;
1079 int k;
1080 {
1081     return(nibble(arr[k>>2],k&3));
1082 }
1083 /*-------------------------------------------------------------------*/
1084 /*
1085 ** Das Array arr wird als Folge von Nibbles zu je n bit (n=1,3,4)
1086 ** aufgefasst. Die Funktion gibt das k-te Nibble zurueck.
1087 ** Vorsicht! Die gueltige Laenge von arr ist nicht bekannt.
1088 */
nibndigit(n,arr,k)1089 PUBLIC int nibndigit(n,arr,k)
1090 int n;      /* bits per digit */
1091 word2 *arr;
1092 long k;
1093 {
1094     int x, i;
1095     long k3;
1096 
1097     if(n == 4)
1098         return(nibdigit(arr,(int)k));
1099     else if(n == 1)
1100         return(nthbit(arr,k));
1101     else if(n == 3) {
1102         k3 = k+k+k;
1103         x = 0;
1104         for(i=2; i>=0; i--) {
1105             x <<= 1;
1106             if(nthbit(arr,k3+i))
1107                 x |= 1;
1108         }
1109         return(x);
1110     }
1111     else    /* this case should not happen */
1112         return(0);
1113 }
1114 /*-------------------------------------------------------------------*/
nthbit(arr,n)1115 PRIVATE int nthbit(arr,n)
1116 word2 *arr;
1117 long n;     /* zero based */
1118 {
1119     int k, b;
1120     word2 mask = 1;
1121 
1122     k = n >> 4;
1123     b = n & 0xF;
1124     return(arr[k] & (mask << b) ? 1 : 0);
1125 }
1126 /*-------------------------------------------------------------------*/
1127 /*
1128 ** gibt Ascii-code der k-ten Dezimalstelle des bcd-Arrays arr;
1129 ** 0 <= k < Stellenzahl von arr
1130 */
nibascii(arr,k)1131 PUBLIC int nibascii(arr,k)
1132 word2 *arr;
1133 int k;
1134 {
1135     return(hexascii(nibdigit(arr,k)));
1136 }
1137 /*-------------------------------------------------------------------*/
hexascii(n)1138 PUBLIC int hexascii(n)
1139 int n;
1140 {
1141     if(0 <= n && n <= 9)
1142         return('0' + n);
1143     else if(n >= 10 && n <= 15)
1144         return(('A'-10) + n);
1145     else    /* this case should not happen */
1146         return('0');
1147 }
1148 /*-------------------------------------------------------------------*/
1149 /*
1150 ** verschiebt bcd-array (arr,n) um k Stellen
1151 ** k > 0: Links-Shift; k < 0: Rechts-Shift
1152 ** Rueckgabewert: Anzahl der Dezimal-Stellen
1153 */
shiftbcd(arr,n,k)1154 PUBLIC int shiftbcd(arr,n,k)
1155 word2 *arr;
1156 int n, k;
1157 {
1158     int b, len;
1159 
1160     if(-k >= n)
1161         return(0);
1162     b = k<<2;
1163     len = (n + 3)>>2;
1164     len = shiftarr(arr,len,b);
1165     return(n + k);
1166 }
1167 /*-------------------------------------------------------------------*/
incbcd(x,n,a)1168 PUBLIC int incbcd(x,n,a)
1169 word2 *x;
1170 int n;
1171 unsigned a;
1172 {
1173     int i, len;
1174     unsigned u;
1175 
1176     if(a == 0)
1177         return(n);
1178     len = (n + 3)>>2;
1179     for(i=0; a && i<len; i++) {
1180         u = bcd2int(x[i]);
1181         u += a;
1182         if(u < DECBASE)
1183             a = 0;
1184         else {
1185             a = 1;
1186             u -= DECBASE;
1187         }
1188         x[i] = int2bcd(u);
1189     }
1190     if(a)
1191         x[len++] = a;
1192     n = ((len-1)<<2) + niblen(x[len-1]);
1193     return(n);
1194 }
1195 /*********************************************************************/
1196