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